将Git重置到提交状态,但不改变HEAD为分离状态

27

我想将git工作副本的文件恢复到给定的提交版本,但不将该提交版本设置为HEAD提交。

如果我使用git checkout命令切换到给定的提交版本,那么我会得到一个分离的HEAD状态,之后提交更改后,提交树看起来会像这样:

A
|
B
|
C  
| \
D  E

我希望获得的行为是:

A
|
B
|
C
|
D
| <- git command so my files are restored to C, but my HEAD still points to D
E

谢谢


2
提交不应该在B的顶部吗?你打算如何处理合并冲突? - Benjamin Bannier
3
不确定你真正想要达到什么目的,也不太确定你如何处理合并冲突/工作树变化,但你尝试过使用 git checkout <commit> . 命令吗?请注意,此命令需要谨慎使用。 - knittl
是的,它应该挂在C上,我的错。我会编辑问题。我的意图是用提交“C”的文件替换我的工作区中的所有文件,而不将C设置为我的头提交。如果将'C'设置为我的HEAD提交,它将处于分离的HEAD状态。 - Josep Rodríguez López
3个回答

29
这应该就行了:
git reset --hard C
git reset --soft D

首先,你需要将 HEAD、索引和工作目录重置为 C
然后,你需要将 HEAD 重置为 D(只重置 HEAD,这与 "git reset --soft 的实用用途" 中所解释的一样)。

请注意,在此时进行提交将创建一个具有 C 内容的新提交,将 D 替换为看起来像 CD'
这将改变历史记录,与简单的 git reset --hard C 没有太大区别。

另一种选择是在 D 之上使用 git revert C,但是 D 仍将出现在历史记录中,这可能不是你想要的。


1
提交 D 不会被替换(据我所见)。另外 reset --hard 会删除所有工作树更改(但可能是必要的)。 - knittl
没错,运行得非常好。 - Josep Rodríguez López
1
太棒了!正是我需要的,可以将来自不同分支的更改集作为未暂存的增量获取到另一个分支的工作树中。 - timmwagener

27

VonC的答案需要您执行一个回合旅程。 您可以通过单个“git checkout”实现相同的效果。

git checkout C ./

请注意,您必须提供./,否则git将实际检出指定的分支或提交。


5
这个答案没有处理分支 C 中已删除或移动文件的情况,它只是让它们保留在那里。 - Dietrich Epp

7

如果需要脚本化此操作,相关的管道命令如下:

git read-tree C
git checkout-index -f -a

尽管我不知道原因,但当我从脚本运行时,除了执行上述命令外,还必须执行以下操作,否则会出现关于补丁未应用于索引的错误:
git update-index -q --refresh

1
刚刚关于 git update-index -q --refresh 的那部分帮了我解决一个完全无关的问题。谢谢 :-) - Jan
不错。请注意,这将使来自C的文件保留在索引中(read-tree将它们放入索引中,而checkout-index则更新工作树),而其他答案仅更改工作树。 - Scott McPeak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接