From: phillip.wood123@gmail.com Date: Tue, 14 May 2024 10:01:36 GMT Subject: Re: Checkout to different directory at certain commit without changing index Message-ID: <45674580-e7f6-48aa-ac17-3e0b96acace9@gmail.com> In-Reply-To: Hi Ondra On 13/05/2024 18:23, Ondra Medek wrote: > 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 > Thanks very much > > Ondra > > On Mon, 13 May 2024 at 17:28, Phillip Wood 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 ; >>> 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 -- ./ >>> >>> 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 >>>