我在编辑器中打开了文件“main.cpp”。

我也想在编辑器中看到“main.cpp”的先前修订。

我现在的做法是这样的。

close "main.cpp" in the editor

prompt> mv main.cpp tmp
prompt> git checkout HEAD^ main.cpp
prompt> mv main.cpp old_main.cpp
prompt> mv tmp main.cpp
prompt>

open "main.cpp" and "old_main.cpp" in the editor

它是否可以简化,这样我就不必在编辑器中关闭“main.cpp”了?

我所希望的是一个git-checkout的变体,它可以做到这一点。


更新:我使用git在mac osx 10.5.7

prompt> git --version
git version 1.6.0.4
prompt> 

Jakub narylbski回答:

prompt> git show HEAD^:dir1/dir2/dir3/main.cpp > old_main.cpp
prompt>

更新3:Karmi的回答,对于一个具体的修订:

prompt> git show 4c274dd91dc:higgs/Higgs.xcodeproj/project.pbxproj > old_project.pbxproj
prompt> 

当前回答

我无法让@kxr的答案工作。我发现这个更简单:

# Rename the current file.
mv path/to/file.txt path/to/file_current.txt`

# Checkout some other version of that file.
git checkout <commit> -- path/to/file.txt

这比使用git show的公认答案要好,因为它保留了不可见的字符。

注意:在上面的代码中,文件的“其他版本”将保持原始文件名,而当前文件是您必须重命名的文件。

这里是一个git别名,它在一行中完成这个任务。这个命令实际上使当前文件保持原来的文件名:

Restore-as = "! "Mv $1 $1_tmp && git checkout $3 - $1 && git restore - staging $1 && Mv $1 $2 && Mv $1_tmp $1 #”(参见这里了解为什么我们需要#后缀)

然后可以这样使用:git restore-as path/to/file.txt path/to/file_old.txt <commit>

其他回答

单文件用例

为了获得一致的签出行为,包括自锁等,使用一个辅助文件夹(以TEMP为例),并从旧的/不同的<commit>恢复文件状态,如下所示:

git --work-tree TEMP/ restore main.cpp -s <commit>
mv TEMP/main.cpp old_main.cpp

使用别名使其成为单行命令

git restore-as old_main.cpp main.cpp -s <commit>

创建别名:

git config --global alias.restore-as "!f() { git --work-tree /tmp/ restore $2 $3 $4 $5 $6 && mv -iv /tmp/$2 $1; }; f"

(最好在创建/tmp/后,将/tmp/替换为用于此类操作的目录-例如/tmp/gitmv。)

注意:

git show <commit>:main.cpp > old_main.cpp

. .只会从存储库中产生一个原始读取。

使用第二个工作树——链接的或匿名的

一个长期的并行工作树(与存储库的主工作树相链接/已知)可以通过git-worktree (git v2.6.7以来的新功能)使用,并且可以将它的HEAD放在不同的分支/ <commit>:

git worktree add [<options>] <new-worktree-path> [<commit-ish>]

工作树可以在没有初始签出(——no-checkout)的情况下创建,然后可以配置稀疏签出,或者通过git restore -s <commit> <file(s)/sub-dir>检索选择的单个文件/子dirs

类似地,可以创建一个额外的匿名工作树(共享HEAD),只需将包含内容的.git文件放入其中

gitdir: <MAIN-REPO-WORKTREE>/.git

你可以使用git show:

git show HEAD^:main.cpp > old_main.cpp

(注意HEAD^和main.cpp之间有冒号[:]。)<revision>:<path>语法在git rev-parse manpage中描述,在“指定修订”部分的最后一点旁边:

<rev>:<path>, e.g. HEAD:README, :README, master:./README A suffix : followed by a path names the blob or tree at the given path in the tree-ish object named by the part before the colon. :path (with an empty part before the colon) is a special case of the syntax described next: content recorded in the index at the given path. A path starting with ./ or ../ is relative to the current working directory. The given path will be converted to be relative to the working tree’s root directory. This is most useful to address a blob or tree from a commit or tree that has the same tree structure as the working tree.

注意,这里的<path>是相对于项目的顶部目录的完整路径,即。git/ directory目录。(或者,更确切地说,到“<revision>”,通常可以是任何<树状>,即表示树的东西。)

如果你想使用相对于当前目录的路径,你需要使用。/<path>语法(或../从当前目录往上的路径)。

编辑2015-01-15:增加相对路径语法


在大多数情况下,你可以使用低级(管道)git cat-file命令得到相同的输出:

git cat-file blob HEAD^:main.cpp > old_main.cpp

我无法让@kxr的答案工作。我发现这个更简单:

# Rename the current file.
mv path/to/file.txt path/to/file_current.txt`

# Checkout some other version of that file.
git checkout <commit> -- path/to/file.txt

这比使用git show的公认答案要好,因为它保留了不可见的字符。

注意:在上面的代码中,文件的“其他版本”将保持原始文件名,而当前文件是您必须重命名的文件。

这里是一个git别名,它在一行中完成这个任务。这个命令实际上使当前文件保持原来的文件名:

Restore-as = "! "Mv $1 $1_tmp && git checkout $3 - $1 && git restore - staging $1 && Mv $1 $2 && Mv $1_tmp $1 #”(参见这里了解为什么我们需要#后缀)

然后可以这样使用:git restore-as path/to/file.txt path/to/file_old.txt <commit>

再补充一下Jakub的回答:如果只对终端中的文件内容感兴趣,甚至不必将输出重定向到带>的文件。你可以运行$ git show 58a3db6:path/to/your/file.txt。