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

Mil*_*kov 789 git single-file

我有一个Git存储库,我想看看几个月前一些文件的样子.我在那个日期找到了修改版,而且它是27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8.我需要查看一个文件的外观,并将其保存到文件中.

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

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt
Run Code Online (Sandbox Code Playgroud)

但是,此命令显示diff而不是文件内容.我知道我以后可以使用类似的东西PAGER=cat并将输出重定向到文件,但我不知道如何获得实际的文件内容.

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

Von*_*onC 700

要完成您自己的答案,语法确实如此

git show object
git show $REV:$FILE
git show somebranch:from/the/root/myfile.txt
git show HEAD^^^:test/test.py
Run Code Online (Sandbox Code Playgroud)

该命令采用通常的修订方式,这意味着您可以使用以下任何一种方式:

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

提示重要的是要记住,使用" git show"时,始终指定存储库根目录的路径,而不是当前目录位置.

(虽然Mike Morearty提到,至少在git 1.7.5.4中,你可以通过./在路径的开头加上" " 来指定相对路径 - 例如:

git show HEAD^^:./test.py
Run Code Online (Sandbox Code Playgroud)

)


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

git restore
显示提交中的一个或多个"blob"对象的列表

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

git restore -s <SHA1>     -- afile
git restore -s somebranch -- afile
Run Code Online (Sandbox Code Playgroud)

git-ls-tree列出了$ REV版本中$ file的对象ID,这是从输出中删除并用作git-cat-file的参数,它应该被称为git-cat-object,并且只是转储stdout的那个对象.


注意:自Git 2.11(2016年第4季度)起,您可以将内容过滤器应用于-s输出!

请参阅提交3214594,提交7bcf341(2016年9月9日),提交7bcf341(2016年9月9日),并提交b9e62f6,提交16dcc29(2016年8月24日)作者:Johannes Schindelin(somebranch).
(由Junio C -SWHamano合并- -提交7889ed2,2016年9月21日)

--staged --worktree:支持git ls-tree <rev>/ git cat-file blob <file-SHA1>批处理模式

即使" git cat-file"是一个采用文件系统数据流并将其放入Git对象存储的工具,也允许执行"外部世界到Git"的转换(例如,行尾转换和应用程序)清理过滤器),默认情况下从早期就开始使用它的反向操作" dscho",它从Git对象存储中获取一个对象并外部化以供外部使用,缺少一个等效的机制.经营"Git-to-outside-world"

git restore -s <SHA1> -SW -- afile
Run Code Online (Sandbox Code Playgroud)

注意:" gitster"最近开始分段(2017年),已在Git 2.5(2017年第4季度)中更正

请参阅Jeff King()提交cc0ea7c(2017年9月21日).(由Junio C Hamano合并- -提交bfbc2fc,2017年9月28日)cat-file
--textconv

  • @Gaui但是'git checkout`会用另一个版本覆盖**你的文件,而不是`git show`,它允许你用不同的名字保存它,以便你得到并看到*both*(当前版本和旧版本).从问题中不清楚OP是否想要用旧版本替换*当前版本. (12认同)
  • 我想指出`^^^`也可以更一般地写成`~~~`或者更好,`~3`.使用tildes还具有不触发某些shell(例如zsh)的文件名匹配的优点. (9认同)
  • `git checkout [分支| 修订版] filepath`是正确的命令 (8认同)
  • @Oscar自`git show`本质上将内容转储到`stdout`(标准输出),你可以简单地将该输出重定向到你想要的任何文件(http://tldp.org/LDP/abs/html/io-redirection的.html). (6认同)
  • 我没有足够的旧git来检查:1.5.x之前的`git rev-parse`句柄`rev:path`语法?(在更新的git中你可以`git cat-file -p $ REV:path`.但是,`git show`也适用于目录路径,因此它不仅更短,而且通常更接近你想要的.) (2认同)
  • @Timo `git restore -s &lt;SHA1&gt; -SW -- afile` 将恢复工作树和索引,这意味着它就像恢复文件一样,并执行 `git add -- file` 来添加您想要的内容刚刚恢复到索引,准备提交。 (2认同)

c-a*_*c-a 495

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

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt
Run Code Online (Sandbox Code Playgroud)

要么

git checkout mybranchname path/to/file.txt
Run Code Online (Sandbox Code Playgroud)

然后,您必须提交这些更改,以使它们在当前分支中有效.

  • 请注意,这将覆盖该路径中的现有文件,而`git show SHA1:PATH`解决方案仅打印到stdout. (72认同)
  • 最简单的解决方案,这就是git-checkout的设计目的 - 指定路径名意味着只检查匹配的文件.从git-checkout手册页:git checkout master~2 Makefile (4认同)

Mil*_*kov 143

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

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt
Run Code Online (Sandbox Code Playgroud)

  • 不一定是完整的道路.来自git根目录的路径(那些来自`git show --name-only`的人也足够了 (7认同)
  • 嗯,从存储库根目录的完整路径.更好地看看我给出的例子."满"之前没有前导斜线. (7认同)
  • 仅供参考,如果您在子目录中,也可以成功使用./filename.ext. (7认同)

jma*_*eli 91

最简单的方法是这样写:

git show HASH:file/path/name.ext > some_new_name.ext
Run Code Online (Sandbox Code Playgroud)

哪里:

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

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:my_file.txt > my_file.txt.OLD
Run Code Online (Sandbox Code Playgroud)

这将把my_file.txt从版本27cf8e保存为名为my_file.txt.OLD的新文件

它是用Git 2.4.5测试的.

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

例:

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8~1:deleted_file.txt > deleted_file.txt
Run Code Online (Sandbox Code Playgroud)

  • 附加信息:您可以使用 git log 获取哈希值 (2认同)

Ale*_*son 10

在Windows中,使用Git Bash:

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


jsi*_*ina 9

git checkout {SHA1} -- filename
Run Code Online (Sandbox Code Playgroud)

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


pro*_*tos 9

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

git reset <hash> /path/to/file
Run Code Online (Sandbox Code Playgroud)

在你的例子中:

git reset 27cf8e8 my_file.txt
Run Code Online (Sandbox Code Playgroud)

这样做的作用是,它将恢复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 commit和)将更新从旧版本添加到新版本,仅适用于某些帅哥git restore file.txt

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

git reset -p 27cf8e8 my_file.txt
Run Code Online (Sandbox Code Playgroud)

因此git reset,使用路径可以让您非常灵活地检索文件的特定版本,以与当前签出的版本进行比较,并且如果您选择这样做,则可以完全恢复或仅部分恢复到该版本。


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

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

git show :file.txt
Run Code Online (Sandbox Code Playgroud)

输出到标准输出或

git show :file.txt > file_at_27cf8e8.txt
Run Code Online (Sandbox Code Playgroud)

但如果这就是你想要的,那么git show按照其他人的建议直接运行git show 27cf8e8:file.txt当然要直接得多。

不过,我将保留这个答案,因为git show直接运行可以让您立即获取旧版本,但是如果您想用它做某事,那么从那里进行操作并不像重置该版本那么方便在索引中。


Mr_*_*s_D 7

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

$ echo "`git show 60d8bdfc:src/services/LocationMonitor.java`" >> LM_60d8bdfc.java
Run Code Online (Sandbox Code Playgroud)

"需要引号,因此保留了换行.

  • 我真的不明白为什么你会使用echo,有或没有引号.我不明白为什么你会想要输出重定向的附加形式.简单地编写是不是更好:git show 60d8bdfc:src/services/LocationMonitor.java> LM_60d8bdfc.java如果由于某种原因你真的想强制使用dos风格的行结尾,你可以通过unix2dos进行管道传输.但是我从来没有发现在Windows上保留dos line-endings有点用处,因为我在Windows上使用的记事本以外的任何文本工具都可以处理unix样式的行. (23认同)
  • git show 60d8bdfc:src/services/LocationMonitor.java >> LM_60d8bdfc.java为我工作. (4认同)
  • 不要使用双引号,因为如果您的文件字符看起来像一个 shell 变量,即 $LANG,它将被替换。@LưuVĩnhPhúc 是保护程序。也不要使用 &gt;&gt; 如果文件存在并可能导致错误,它将附加文件 (2认同)

Adr*_*wan 5

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

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1
Run Code Online (Sandbox Code Playgroud)