git-checkout新名称下的旧文件修订版

neo*_*eye 250 git

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
Run Code Online (Sandbox Code Playgroud)

可以简化,所以我不必在编辑器中关闭"main.cpp"吗?

我希望的是一个git-checkout可以做到这一点的变体.


更新:我在mac osx 10.5.7上使用git

prompt> git --version
git version 1.6.0.4
prompt> 
Run Code Online (Sandbox Code Playgroud)

UPDATE2:JakubNarębski的回答是:

prompt> git show HEAD^:dir1/dir2/dir3/main.cpp > old_main.cpp
prompt>
Run Code Online (Sandbox Code Playgroud)

更新3:Karmi的答案,针对特定修订:

prompt> git show 4c274dd91dc:higgs/Higgs.xcodeproj/project.pbxproj > old_project.pbxproj
prompt> 
Run Code Online (Sandbox Code Playgroud)

Jak*_*ski 286

您可以使用"git show":

prompt> git show HEAD^:main.cpp > old_main.cpp
Run Code Online (Sandbox Code Playgroud)

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

  • <rev>:<path>,例如HEAD:README,:README,master:./ README

    :后跟路径的后缀命名在冒号前面的部分命名的树形对象中给定路径上的blob或树.:path(在冒号前面有一个空部分)是下面描述的语法的特例:在给定路径的索引中记录的内容.

    以当前工作目录开头./../相对于当前工作目录的路径.给定路径将转换为相对于工作树的根目录.这对于从具有与工作树具有相同树结构的提交或树来解决blob或树最有用.

请注意,<path>这是相对于项目的顶级目录FULL路径,即带有目录的目录.(或者更准确地说是" <revision> "(通常可以是任何<tree-ish>,即表示树的东西)).git/

如果要使用相对于当前目录的路径,则需要使用./<path>语法(或../path从当前目录开始).

编辑2015-01-15:添加了有关相对路径语法的信息


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

prompt> git cat-file blob HEAD^:main.cpp > old_main.cpp
Run Code Online (Sandbox Code Playgroud)

  • "git show HEAD ^ main.cpp"(HEAD ^和main.cpp之间的空格)与"git show HEAD ^:main.cpp"(HEAD ^和main.cpp之间的_colon_':')不同. (7认同)
  • 我对一个完整的副本感兴趣,但git-show只显示了差异..我试过玩--pretty选项..提示> git show --pretty = fuller HEAD ^ main.cpp但它没有解决它. (3认同)
  • 这可能意味着你给出了错误的PATHNAME(不幸的是因为"git show"魔法git无法给出更好的错误信息).它应该是相对于项目的顶级目录的FULL路径名:$(git ls-tree -r --name-only HEAD ^ | grep main.cpp) (2认同)
  • 而不是完整路径,来自文档:"以./或../开头的路径是相对于当前工作目录的." 适用于我的1.8.5版本. (2认同)

kar*_*rmi 23

只是添加到Jakub的答案:>如果您只想在终端中浏览文件内容,则甚至不必将输出重定向到文件.你可以跑$ git show 58a3db6:path/to/your/file.txt.


kxr*_*kxr 11

单个文件用例

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

git --work-tree TEMP/ restore main.cpp -s <commit>
mv TEMP/main.cpp old_main.cpp
Run Code Online (Sandbox Code Playgroud)

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

git restore-as old_main.cpp main.cpp -s <commit>
Run Code Online (Sandbox Code Playgroud)

创建别名:

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

(最好替换/tmp/为为此类操作保留的目录 - 例如/tmp/gitmv- 创建后。)

笔记:

git show <commit>:main.cpp > old_main.cpp
Run Code Online (Sandbox Code Playgroud)

..只会从存储库中生成原始读取内容。

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

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

git worktree add [<options>] <new-worktree-path> [<commit-ish>]
Run Code Online (Sandbox Code Playgroud)

可以在没有初始签出 ( ) 的情况下创建工作树--no-checkout,然后sparse-checkout可以对其进行配置,或者可以通过以下方式检索仅选择的单个文件/子目录git restore -s <commit> <file(s)/sub-dir>

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

gitdir: <MAIN-REPO-WORKTREE>/.git
Run Code Online (Sandbox Code Playgroud)