Re: Checkout to different directory at certain commit without changing index
- From
- phillip.wood123@gmail.com <phillip.wood123@gmail.com>
- Date
- May 14, 2024, 10:01 UTC
- Message-ID
- <45674580-e7f6-48aa-ac17-3e0b96acace9@gmail.com>
- In-Reply-To
- <CAJsoDaFhTcm0fEw3+Ba4PvTjPYxscALeLN2kBgs4YYz8Bg-R7g@mail.gmail.com>
Hi Ondra
On 13/05/2024 18:23, Ondra Medek wrote:
Show 9 quoted lines
> Hi Phillip, > > besides dependency on tar, I do not want to use git-archive because > it's influenced by export-ignore and export-subst attributes, too (as > I have mentioned). > > Thanks for git read-tree, seems it's exactly what I need. Just git > read-tree has complained that -u switch needs -m or --reset switches. > And I have simplified it to
Sorry I'd forgotten about that
> git --work-tree="$destdir" read-tree --index-output="$destdir".git -u > --reset "$commit"
You should be aware that --reset will happily overwrite files in the destination directory, using -m instead would stop existing files being overwritten. If you change to -m you must set GIT_INDEX_FILE instead of using --index-output otherwise only the files that differ from the current index will be checked out. Also using a relative path for the index file specified with --index-output or GIT_INDEX_FILE is error prone when running the command from a subdirectory of the repository. I avoided suggesting --work-tree because I wasn't sure how it handled relative paths when run from a subdirectory but I think it is in fact ok.
> rm -f "$destdir"/.git > > May I post this solution to the SO thread I have mentioned?
That's entirely up to you but I'd make sure it works with relative paths and note the difference between --reset and -m.
Best Wishes
Phillip
Show 70 quoted lines
> Thanks very much
>
> Ondra
>
> On Mon, 13 May 2024 at 17:28, Phillip Wood <phillip.wood123@gmail.com> wrote:
>>
>> Hi Ondra
>>
>> On 13/05/2024 08:26, Ondra Medek wrote:
>>> Hello,
>>> I need a simple script for unskilled users to do a fast checkout (LFS
>>> friendly) of the current local Git clone at a certain commit to a
>>> different directory I.e. something like "copy at a point in history".
>>
>> I think using
>>
>> git archive "$commit" --format=tar |
>> { cd "$output_directory" && tar -xf -; }
>>
>> is probably the simplest solution. If you don't want to rely on tar then
>> something like
>>
>> GIT_DIR="$(git rev-parse --path-format=absolute --git-dir)" &&
>> GIT_COMMON_DIR="$(git rev-parse --path-format=absolute
>> --git-common-dir)" || exit
>> GIT_INDEX_FILE="$GIT_DIR/tmp-index-$$"
>> export GIT_DIR GIT_COMMON_DIR GIT_INDEX_FILE
>> unset GIT_WORK_TREE
>> mkdir "$output_directory" && cd "$output_directory" &&
>> git read-tree -u "$commit"
>> status=$?
>> rm "$GIT_INDEX_FILE"
>> exit $status
>>
>> Which uses a temporary index file should work (note I haven't tested
>> it). You may want to add "--recurse-submodules" and/or
>> "--no-sparse-checkout" to the "git read-tree" commandline.
>>
>> Best Wishes
>>
>> Phillip
>>
>>> IMO all possible solutions are summarized in this thread
>>> https://stackoverflow.com/questions/160608/do-a-git-export-like-svn-export
>>> I describe some of them with my remarks:
>>>
>>> - git checkout-index : works with HEAD only.
>>> - git archive: influenced by export-ignore and export-subst
>>> attributes, so may not produce exact copy of sources. (And needs tar).
>>> - git worktree add -d : needs cleanup: git prune or git remove.
>>> - git clone: Unfortunately, -b param cannot work with commit hash and
>>> does not respect local worktree settings (e.g. autocrlf). So, a
>>> solution may be a bit complicated: git clone -s -n . dest/path ; cp
>>> .git/config dest/path/.git ; cd dest/path ; git co -q <commit-ish> ;
>>> rm -rf .git
>>> - git checkout: Unfortunately, modifies Git index, so some action to
>>> revert index is necessary after: git --work-tree=/path/to/checkout/
>>> checkout -f -q <tree-ish> -- ./
>>>
>>> For me, the best solution is with git clone, because it does not
>>> modify Git index nor any source working tree settings, so no cleanup
>>> is necessary. But it's a bit complicated, though. It seems to me that
>>> "git checkout" could do this better and simpler if it would have some
>>> param to not modify the Git index. Is it possible to enhance git
>>> checkout? Or is there any other simple solution not mentioned in the
>>> SO thread?
>>>
>>> Thank you
>>> Ondra Medek
>>>