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

后端 未结 10 1259
臣服心动
臣服心动 2020-11-22 15:50

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; it\'s 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8<

相关标签:
10条回答
  • 2020-11-22 16:03

    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.

    0 讨论(0)
  • 2020-11-22 16:05

    In addition to all the options listed by other answers, you can use git reset with the Git object (hash, branch, HEAD~x, tag, ...) of interest and the path of your file:

    git reset <hash> /path/to/file
    

    In your example:

    git reset 27cf8e8 my_file.txt
    

    What this does is that it will revert my_file.txt to its version at the commit 27cf8e8 in the index while leaving it untouched (so in its current version) in the working directory.

    From there, things are very easy:

    • you can compare the two versions of your file with git diff --cached my_file.txt
    • you can get rid of the old version of the file with git restore --staged file.txt (or, prior to Git v2.23, git reset file.txt) if you decide that you don't like it
    • you can restore the old version with git commit -m "Restore version of file.txt from 27cf8e8" and git restore file.txt (or, prior to Git v2.23, git checkout -- file.txt)
    • you can add updates from the old to the new version only for some hunks by running git add -p file.txt (then git commit and git restore file.txt).

    Lastly, you can even interactively pick and choose which hunk(s) to reset in the very first step if you run:

    git reset -p 27cf8e8 my_file.txt
    

    So git reset with a path gives you lots of flexibility to retrieve a specific version of a file to compare with its currently checked-out version and, if you choose to do so, to revert fully or only for some hunks to that version.


    Edit: I just realized that I am not answering your question since what you wanted wasn't a diff or an easy way to retrieve part or all of the old version but simply to cat that version.

    Of course, you can still do that after resetting the file with:

    git show :file.txt
    

    to output to standard output or

    git show :file.txt > file_at_27cf8e8.txt
    

    But if this was all you wanted, running git show directly with git show 27cf8e8:file.txt as others suggested is of course much more direct.

    I am going to leave this answer though because running git show directly allows you to get that old version instantly, but if you want to do something with it, it isn't nearly as convenient to do so from there as it is if you reset that version in the index.

    0 讨论(0)
  • 2020-11-22 16:10

    Using git show

    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
    

    )

    Using git restore

    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)

    Using low-level git plumbing commands

    Before git1.5.x, this 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)

    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)

    0 讨论(0)
  • 2020-11-22 16:15
    git checkout {SHA1} -- filename
    

    this command get the copied file from specific commit.

    0 讨论(0)
  • 2020-11-22 16:16

    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
    0 讨论(0)
  • 2020-11-22 16:16

    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.

    0 讨论(0)
提交回复
热议问题