How to retrieve a single file from a specific revision in Git?

不羁岁月 提交于 2019-11-25 23:50:29

问题


I have a Git repository and I\'d like to see how some files looked a few months ago. I found the revision at that date, and it\'s 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8. I need to see what did one file looks like and also save that to a file.

I managed to see the file using gitk, but it doesn\'t have an option to save it. I tried with command-line tools, the closest I got was:

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

However, this command shows a diff and not the file contents. I know I can later use something like PAGER=cat and redirect output to a file, but I don\'t know how to get to the actual file content.

Basically, I\'m looking for something like svn cat.


回答1:


To complete your own answer, the syntax is indeed

git show object
git show $REV:$FILE
git show somebranch:from/the/root/myfile.txt
git show HEAD^^^:test/test.py

The command takes the usual style of revision, meaning you can use any of the following:

  1. branch name (as suggested by ash)
  2. HEAD + x number of ^ characters
  3. The SHA1 hash of a given revision
  4. The first few (maybe 5) characters of a given SHA1 hash

Tip It's important to remember that when using "git show", always specify a path from the root of the repository, not your current directory position.

(Although Mike Morearty mentions that, at least with git 1.7.5.4, you can specify a relative path by putting "./" at the beginning of the path -- for example:

git show HEAD^^:./test.py

)


With Git 2.23+ (August 2019), you can also use git restore which replaces the confusing git checkout command

git restore -s <SHA1>     -- afile
git restore -s somebranch -- afile

That would restore on the working tree only the file as present in the "source" (-s) commit SHA1 or branch somebranch.
To restore also the index:

git restore -s <SHA1> -SW -- afile

(-SW: short for --staged --worktree)


Before git1.5.x, that was done with some plumbing:

git ls-tree <rev>
show a list of one or more 'blob' objects within a commit

git cat-file blob <file-SHA1>
cat a file as it has been committed within a specific revision (similar to svn cat). use git ls-tree to retrieve the value of a given file-sha1

git cat-file -p $(git-ls-tree $REV $file | cut -d " " -f 3 | cut -f 1)::

git-ls-tree lists the object ID for $file in revision $REV, this is cut out of the output and used as an argument to git-cat-file, which should really be called git-cat-object, and simply dumps that object to stdout.


Note: since Git 2.11 (Q4 2016), you can apply a content filter to the git cat-file output!

See commit 3214594, commit 7bcf341 (09 Sep 2016), commit 7bcf341 (09 Sep 2016), and commit b9e62f6, commit 16dcc29 (24 Aug 2016) by Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit 7889ed2, 21 Sep 2016)

cat-file: support --textconv/--filters in batch mode

Even though "git hash-objects", which is a tool to take an on-filesystem data stream and put it into the Git object store, allowed to perform the "outside-world-to-Git" conversions (e.g. end-of-line conversions and application of the clean-filter), and it had the feature on by default from very early days, its reverse operation "git cat-file", which takes an object from the Git object store and externalize for the consumption by the outside world, lacked an equivalent mechanism to run the "Git-to-outside-world"

git config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <"
git cat-file --textconv --batch

Note: "git cat-file --textconv" started segfaulting recently (2017), which has been corrected in Git 2.15 (Q4 2017)

See commit cc0ea7c (21 Sep 2017) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit bfbc2fc, 28 Sep 2017)


Note that to override/replace a file with a past content, you should not use the confusing git checkout command anymore, but git restore (Git 2.23+, August 2019)

git restore -s <SHA1> -- afile

That would restore on the working tree only the file as present in the "source" (-s) commit SHA1.
To restore also the index:

git restore -s <SHA1> -SW -- afile

(-SW: short for --staged --worktree)




回答2:


If you wish to replace/overwrite the content of a file in your current branch with the content of the file from a previous commit or a different branch, you can do so with these commands:

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

or

git checkout mybranchname path/to/file.txt

You will then have to commit those changes in order for them to be effective in the current branch.




回答3:


You need to provide the full path to the file:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt



回答4:


The easiest way is to write:

git show HASH:file/path/name.ext > some_new_name.ext

where:

  • HASH is the Git revision SHA-1 hash number
  • file/path/name.ext is name of the file you are looking for
  • some_new_name.ext is path and name where the old file should be saved

Example

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:my_file.txt > my_file.txt.OLD

This will save my_file.txt from revision 27cf8e as a new file with name my_file.txt.OLD

It was tested with Git 2.4.5.

If you want to retrieve deleted file you can use HASH~1 (one commit before specified HASH).

EXAMPLE:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt



回答5:


In Windows, with Git Bash:

  • in your workspace, change dir to the folder where your file lives
  • git show cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file.ext > old.ext



回答6:


And to nicely dump it into a file (on Windows at least) - Git Bash:

$ echo "`git show 60d8bdfc:src/services/LocationMonitor.java`" >> LM_60d8bdfc.java

The " quotes are needed so it preserves newlines.




回答7:


This will help you get all deleted files between commits without specifying the path, useful if there are a lot of files deleted.

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1



回答8:


git checkout {SHA1} -- filename

this command get the copied file from specific commit.




回答9:


Get the file from a previous commit through checking-out previous commit and copying file.

  • Note which branch you are on: git branch
  • Checkout the previous commit you want: git checkout 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
  • Copy the file you want to a temporary location
  • Checkout the branch you started from: git checkout theBranchYouNoted
  • Copy in the file you placed in a temporary location
  • Commit your change to git: git commit -m "added file ?? from previous commit"


来源:https://stackoverflow.com/questions/610208/how-to-retrieve-a-single-file-from-a-specific-revision-in-git

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!