我有一个Git存储库,我想看看几个月前一些文件的样子。我找到了那个日期的修订本;这是27 cf8e84bb88e24ae4b4b3df2b77aab91a3735d8。我需要看到一个文件看起来像什么,并将其保存为(“新”)文件。

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

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

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

基本上,我在找svn cat之类的东西。


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

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

使用git show

为了完成你自己的回答,语法确实是

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

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

分支名称(由ash建议) HEAD + x ^个字符数 给定修订的SHA1哈希值 给定SHA1散列的前几个字符(可能是5个)

提示:重要的是要记住,当使用“git show”时,总是指定一个来自存储库根的路径,而不是当前目录的位置。

(尽管Mike Morearty提到过,至少在git 1.7.5.4中,你可以通过输入"。/"在路径的开头。例如:

git show HEAD^^:./test.py

)

使用git恢复

在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:阶段性工作树的缩写)


正如starwarswii的评论所指出的那样

它允许您将内容管道到一个文件中,如果您只想快速比较来自提交的文件,这是非常棒的。 例如,你可以做: Git显示1234:path/to/file.txt > new.txt Git显示1234~:path/to/file.txt > old.txt 然后比较它们。


使用低级git管道命令

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

Git ls-tree <rev> 在提交中显示一个或多个“blob”对象的列表

git cat-file blob <file-SHA1> . txt Cat在特定修订中提交的文件(类似于SVN 猫)。 使用git ls-tree来检索给定file-sha1的值

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

git-ls-tree列出了修订版$REV中$file的对象ID,这被从输出中删除,并用作git-cat-file的参数,它应该被称为git-cat-object,并简单地将该对象转储到stdout。


注意:从Git 2.11 (Q4 2016)开始,您可以对Git cat文件输出应用内容过滤器。

看到 提交3214594, commit 7bcf341(2016年9月9日), commit 7bcf341(2016年9月9日),以及 提交b9e62f6, Johannes Schindelin (dscho)提交16dcc29(2016年8月24日)。 (由Junio C Hamano—gitster—在commit 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年第四季度)中得到更正

参见Jeff King (peff)的commit cc0ea7c(2017年9月21日)。 (由Junio C Hamano—gitster—在commit bfbc2fc中合并,2017年9月28日)


如果你想用以前提交的文件或不同分支的文件内容替换/覆盖当前分支中的文件内容,你可以使用这些命令:

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

or

git checkout mybranchname path/to/file.txt

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


通过签出以前的提交并复制文件,从以前的提交中获取文件。

注意你在哪个分支上:git分支 签出你想要的上一个提交:git签出27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 将需要的文件复制到临时位置 签出你开始的分支:git Checkout thebranchyounotes 复制放入临时位置的文件 提交你的更改到git: git Commit -m "添加的文件??从之前的提交"


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

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

引号是必需的,所以它保留了换行符。


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

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

在Windows中,使用Git Bash:

在工作空间中,将dir更改为文件所在的文件夹 Git显示cab485c83b53d56846eb883babaaf4dff2f2cc46:./your_file。Ext > old.ext


最简单的方法是这样写:

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

地点:

HASH是Git修订的SHA-1哈希值 文件/道路/的名字。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

git checkout {SHA1} -- filename

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


除了其他答案列出的所有选项,你可以使用git重置感兴趣的git对象(散列,分支,HEAD~x,标签,…)和你的文件路径:

git reset <hash> /path/to/file

在你的例子中:

git reset 27cf8e8 my_file.txt

这样做的目的是将my_file.txt还原为索引中提交27cf8e8处的版本,同时在工作目录中保持它的原形(即当前版本)。

从这里开始,事情变得非常简单:

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).

最后,你甚至可以交互式地选择哪块(s)重置在第一步,如果你运行:

git reset -p 27cf8e8 my_file.txt

所以git重置路径为你提供了很大的灵活性,可以检索文件的特定版本,与当前签出的版本进行比较,如果你选择这样做,还可以完全还原到该版本,或者只还原到该版本的一些块。


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

当然,你仍然可以在重置文件后这样做:

git show :file.txt

输出到标准输出或

git show :file.txt > file_at_27cf8e8.txt

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

我将留下这个答案,因为直接运行git show可以让你立即获得旧版本,但如果你想用它做一些事情,从那里做这件事远不如在索引中重置那个版本那么方便。


使用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在符号链接上使用$REV:$FILE时,它的目标将被打印:

$ git show HEAD:link
test

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

$ git show HEAD:test
tree HEAD:test

foo

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


如果您更喜欢使用GUI来完成此操作,如果您知道文件大约在何时被更改,则以下操作将有效。

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

Git ->查看分支历史 右键单击文件被更改的提交,然后选择查看提交详细信息 在右侧的更改列表中,单击感兴趣的文件。您将看到更改前后完整文件内容的并排比较。只需选择所有并复制文件内容,并粘贴到任何你想要的地方。