如何从 Git 中的特定修订版检索单个文件?

发布于 2024-07-14 07:53:22 字数 427 浏览 9 评论 0原文

我有一个 Git 存储库,我想看看一些文件几个月前的样子。 我在那个日期找到了修订版; 它是27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8。 我需要查看一个文件的样子,并将其另存为(“新”)文件。

我设法使用 gitk 查看该文件,但它没有保存它的选项。 我尝试使用命令行工具,最接近的是:

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

但是,此命令显示差异,而不是文件内容。 我知道我稍后可以使用诸如 PAGER=cat 之类的东西并将输出重定向到文件,但我不知道如何获取实际的文件内容。

基本上,我正在寻找类似 svn cat 的东西。

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. I need to see what one file looks like, and also save it as a ("new") 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

春夜浅 2024-07-21 07:53:22

使用 git show

来完成您自己的答案,语法确实是

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

该命令采用通常的修订风格,这意味着您可以使用以下任何内容:

  1. 分支名称(如 ash建议)
  2. HEAD + x ^ 字符数
  3. 给定版本的 SHA1 哈希值
  4. 给定 SHA1 哈希值的前几个(可能是 5)个字符

提示 记住这一点很重要使用“git show”时,始终指定存储库根目录的路径,而不是当前目录位置。

(尽管 Mike Morearty 提到,至少在 git 1.7.5.4 中,您可以通过输入“来指定相对路径” ./”位于路径开头。例如

git show HEAD^^:./test.py

:)

使用 git Restore

对于 Git 2.23+(2019 年 8 月),您还可以使用 git Restore 替换 令人困惑的 git checkout 命令

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

这只会在工作树上恢复“源”中存在的文件( -s) 提交 SHA1 或分支 somebranch
要恢复索引:(

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

-SW--staged --worktree 的缩写)


评论,作者:starwarswii

它允许您将内容通过管道传输到文件中,如果您只想快速比较提交中的文件,这非常有用。

例如你可以这样做:

git show 1234:path/to/file.txt >   新的.txt  
  git show 1234~:path/to/file.txt >   旧的.txt 
  

然后比较它们。


使用低级 git 管道命令

在 git1.5.x 之前,这是通过一些管道完成的:

git ls-tree
显示提交中一个或多个“blob”对象的列表

git cat-file blob
cat 一个文件,因为它已在特定修订版中提交(类似于 svn
猫)。
使用 git ls-tree 检索给定文件 sha1 的值

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

git-ls-tree 列出修订版中的 $file 的对象 ID $REV,这是从输出中删除并用作 git-cat-file 的参数,它实际上应该被称为 git-cat-object< /code>,然后简单地将该对象转储到 stdout


注意:从 Git 2.11(2016 年第 4 季度)开始,您可以对 git cat-file 输出应用内容过滤器。


提交 3214594,
提交 7bcf341(2016 年 9 月 9 日),
提交 7bcf341(2016 年 9 月 9 日),以及
提交 b9e62f6,
提交 16dcc29(2016 年 8 月 24 日),作者:约翰内斯·辛德林 (dscho)
(由 Junio C Hamano -- gitster -- 合并于 提交 7889ed2,2016 年 9 月 21 日)

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

注意:“git cat-file - -textconv”最近(2017 年)开始出现段错误,已在 Git 2.15(2017 年第 4 季度)中得到纠正。

请参阅 提交 cc0ea7c(2017 年 9 月 21 日),作者:Jeff King (peff).
(由
Junio C Hamano -- gitster -- 合并于 提交 bfbc2fc,2017 年 9 月 28 日)


正如 Kira评论

如果使用LFS文件,则需要通过smudge运行show的输出:

git show master:blends/bigfile.blend |   git lfs 涂抹 >   混合/bigfile.blend 
  

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)


As noted in the comments by starwarswii

It lets you pipe the contents into a file, which is great if you want to just quickly compare files from a commit.

E.g. you can do:

git show 1234:path/to/file.txt > new.txt 
git show 1234~:path/to/file.txt > old.txt

then compare them.


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)


As noted by Kira in the comments:

If you are using LFS files, you need to run the output of show through smudge:

git show master:blends/bigfile.blend | git lfs smudge > blends/bigfile.blend
め七分饶幸 2024-07-21 07:53:22

如果您希望使用先前提交或不同分支中的文件内容替换/覆盖当前分支中的文件内容,您可以使用以下命令来执行此操作:

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

或者

git checkout mybranchname path/to/file.txt

您将必须提交这些更改才能使它们在当前分支中生效。

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.

千鲤 2024-07-21 07:53:22

您需要提供文件的完整路径:

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

You need to provide the full path to the file:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt
奶茶白久 2024-07-21 07:53:22

最简单的方式是这样写:

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

其中:

  • HASH 是 Git 版本 SHA-1 哈希值
  • file/path/name.ext 是名称您要查找的文件
  • some_new_name.ext 是应保存旧文件的路径和名称

示例

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

这将从修订版 27cf8e 中保存 my_file.txt > 作为一个名为 my_file.txt.OLD 的新文件

它已使用 Git 2.4.5 进行了测试。

如果您想检索已删除的文件,可以使用HASH~1(指定HASH之前的一次提交)。

例子:

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

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
永言不败 2024-07-21 07:53:22
git checkout {SHA1} -- filename

此命令从特定提交获取复制的文件。

git checkout {SHA1} -- filename

this command get the copied file from specific commit.

夏の忆 2024-07-21 07:53:22

在 Windows 中,使用 Git Bash:

  • 在工作区中,将 dir 更改为文件所在的文件夹
  • git show cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file.ext > 旧的.ext

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
缺⑴份安定 2024-07-21 07:53:22

除了其他答案列出的所有选项之外,您还可以将 git reset 与 Git 对象(哈希、分支、HEAD~x、标签...)一起使用兴趣和文件路径:

git reset <hash> /path/to/file

在您的示例中:

git reset 27cf8e8 my_file.txt

它的作用是将 my_file.txt 恢复到索引中提交 27cf8e8 的版本,同时保留它在工作目录中保持不变(因此在当前版本中)。

从那里,事情变得非常简单:

  • 您可以使用 git diff --cached my_file.txt 比较文件的两个版本,
  • 您可以使用 git Restore 删除文件的旧版本--staged file.txt (或者,在 Git v2.23 之前,git reset file.txt)如果您决定不喜欢它,
  • 您可以使用以下命令恢复旧版本git commit -m "Restore version of file.txt from 27cf8e8"git Restore file.txt (或者,在 Git v2.23 之前,git checkout - - file.txt
  • 您可以通过运行 git add -p file.txt (然后运行 ​​git commitgit 恢复 file.txt)。

最后,如果运行,您甚至可以交互地选择在第一步中要重置的块:

git reset -p 27cf8e8 my_file.txt

因此带有路径的 git reset 为您提供了很大的灵活性来检索特定版本的文件与当前签出的版本进行比较,如果您选择这样做,则可以完全恢复或仅部分恢复到该版本。


编辑:我刚刚意识到我没有回答你的问题,因为你想要的不是差异或检索部分或全部旧版本的简单方法,而只是cat那个版本。

当然,您仍然可以在重置文件后执行以下操作:

git show :file.txt

输出到标准输出或

git show :file.txt > file_at_27cf8e8.txt

但如果这就是您想要的,请直接使用 git show 27cf8e8:file.txt 运行 git show正如其他人所建议的那样, 当然更直接。

不过,我将保留这个答案,因为直接运行 git show 可以让您立即获取旧版本,但如果您想用它做点什么,那么从如果您在索引中重置该版本,就会出现这种情况。

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.

紫南 2024-07-21 07:53:22

为了很好地将其转储到文件中(至少在 Windows 上) - Git Bash:

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

需要 " 引号,以便保留换行符。

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.

别在捏我脸啦 2024-07-21 07:53:22

这将帮助您在提交之间获取所有已删除的文件,而无需指定路径,如果删除了大量文件,这很有用。

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

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
滥情稳全场 2024-07-21 07:53:22

正如其他人已经指出的那样,使用 git show $REV:$FILE 可能是正确的答案。 我发布了另一个答案,因为当我尝试此方法时,有时会从 git 收到以下错误:

fatal: path 'link/foo' exists on disk, but not in 'HEAD'

当文件路径的部分内容是符号链接时,就会出现问题。 在这些情况下,git show $REV:$FILE 方法将不起作用。 重现步骤:

$ git init .
$ mkdir test
$ echo hello > test/foo
$ ln -s test link
$ git add .
$ git commit -m "initial commit"
$ cat link/foo
hello
$ git show HEAD:link/foo
fatal: path 'link/foo' exists on disk, but not in 'HEAD'

问题是,像 realpath 这样的实用程序在这里没有帮助,因为符号链接可能不再存在于当前提交中。 我不知道有什么好的通用解决方案。 就我而言,我知道符号链接只能存在于路径的第一个组成部分中,因此我通过使用 git show $REV:$FILE 方法两次解决了该问题。 有效的,因为当在符号链接上使用 git show $REV:$FILE 时,会打印其目标:

$ git show HEAD:link
test

而对于目录,该命令将输出一个标头,后跟目录内容:

$ git show HEAD:test
tree HEAD:test

foo

这是 我的情况,我只是检查了第一次调用 git show $REV:$FILE 的输出,如果它只是一行,那么我用要解析的结果替换了路径的第一个组件通过 git 的符号链接。

Using git show $REV:$FILE as it was already pointed out by others is probably the right answer. I'm posting another answer because when I tried this method, I sometimes got the following error from git:

fatal: path 'link/foo' exists on disk, but not in 'HEAD'

The problem occurs when parts of the path to the file are a symbolic link. In those cases, the git show $REV:$FILE method will not work. Steps to reproduce:

$ git init .
$ mkdir test
$ echo hello > test/foo
$ ln -s test link
$ git add .
$ git commit -m "initial commit"
$ cat link/foo
hello
$ git show HEAD:link/foo
fatal: path 'link/foo' exists on disk, but not in 'HEAD'

The problem is, that utilities like realpath don't help here, because the symlink might not exist in the current commit anymore. I don't know about a good general solution. In my case, I knew that the symlink could only exist in the first component of the path, so I solved the problem by using the git show $REV:$FILE method twice. This works, because when git show $REV:$FILE is used on a symlink, then its target gets printed:

$ git show HEAD:link
test

Whereas with directories, the command will output a header, followed by the directory content:

$ git show HEAD:test
tree HEAD:test

foo

So in my case, I just checked the output of the first call to git show $REV:$FILE and if it was only a single line, then I replaced the first component of my path with the result to resolve the symlink through git.

離人涙 2024-07-21 07:53:22

通过检出先前的提交并复制文件来获取先前提交的文件。

  • 记下您所在的分支: gitbranch
  • 签出您想要的上一个提交:git checkout 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8
  • 将您想要的文件复制到临时位置
  • 签出您开始的分支:git checkout theBranchYouNoted code>
  • 复制您放置在临时位置的文件
  • 将更改提交到 git: git commit -m "added file ?? from previous commit"

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"
寻找我们的幸福 2024-07-21 07:53:22

如果您更喜欢使用 GUI 来执行此操作,并且您知道文件大约何时发生更改,则以下操作将起作用。

在安装了 Git 扩展的 Visual Studio 上:

  1. Git -> 查看分支历史记录
  2. 右键单击​​文件发生更改的提交,然后选择“查看提交详细信息”
  3. 在右侧的更改列表上,单击感兴趣的文件。 您将看到更改前后完整文件内容的并排比较。 只需选择全部并复制文件内容并粘贴到您想要的任何位置。

If you prefer to use GUI to do this, the following will work if you know when approximately the file got changed.

On Visual Studio with Git Extension installed:

  1. Git -> View Branch History
  2. Right click on the commit where the file got changed, then choose View Commit Details
  3. On list of changes on the right, click on the file of interest. You'll see side by side comparison of full file content before and after the change. Just select all and copy the file content and paste to anywhere you want.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文