我一直在用git工作一个多月。实际上我昨天才第一次使用复位,但软复位对我来说仍然没有多大意义。
据我所知,我可以使用软重置编辑提交而不改变索引或工作目录,就像使用git commit --amend
一样。
这两个命令是否真的相同(reset --soft
vs commit --amend
)?有任何理由在实际中使用其中一个吗?更重要的是,除了修改提交之外,reset --soft
还有其他用途吗?
答案 0 :(得分:96)
git reset
完全是关于移动HEAD
,and generally the branch ref
问题:工作树和索引怎么样?
与--soft
一起使用时,会移动HEAD
,通常会更新分支参考,只会更新HEAD
。
这与commit --amend
不同:
commit --amend
仅关于不移动HEAD,同时允许重做当前提交)刚刚找到了这个组合的例子:
all into one(章鱼,因为合并了两个以上的分支)提交合并。
Tomas "wereHamster" Carnecky在他的"Subtree Octopus merge" article:
中解释道
- 如果要将一个项目合并到另一个项目的子目录中,并且随后使子项目保持最新,则可以使用子树合并策略。它是git子模块的替代品。
- 章鱼合并策略可用于合并三个或更多分支。正常策略只能合并两个分支,如果你尝试合并更多,git会自动回退到章鱼策略。
问题在于您只能选择一种策略。但我希望将这两者结合起来,以获得一个干净的历史记录,其中整个存储库被原子地更新为新版本。
我有一个超级项目,我们称之为
projectA
,以及一个子项目projectB
,我将其合并到projectA
的子目录中。
(这是子树合并部分)
我也在保留一些本地提交
ProjectA
会定期更新,projectB
每隔几天或几周都有一个新版本,通常取决于projectA
的特定版本。当我决定更新这两个项目时,我不会简单地从
projectA
和projectB
中提取,因为这将为整个项目的原子更新创建两个提交< / strong>即可。
相反,我创建了一个合并提交,其中包含projectA
,projectB
和我的本地提交。 这里棘手的部分是这是一个章鱼合并(三个头),但projectB
需要与子树策略合并。所以这就是我的工作:
# Merge projectA with the default strategy:
git merge projectA/master
# Merge projectB with the subtree strategy:
git merge -s subtree projectB/master
在这里,作者使用reset --hard
,然后read-tree
来恢复前两个合并对工作树和索引所做的操作,但这就是 reset --soft
< / strong>可以提供帮助:
如何重做那两个合并,哪些有效,即我的工作树和索引都没问题,但无需记录这两个提交?
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
现在,我们可以恢复Tomas的解决方案:
# Pretend that we just did an octopus merge with three heads:
echo $(git rev-parse projectA/master) > .git/MERGE_HEAD
echo $(git rev-parse projectB/master) >> .git/MERGE_HEAD
# And finally do the commit:
git commit
所以,每次:
git reset --soft
就是答案。
答案 1 :(得分:32)
&#34;糟糕。这三个提交可能只是一个。&#34;
因此,撤消最后3次(或其他)提交(不影响索引或工作目录)。然后将所有更改作为一个提交。
> git add -A; git commit -m "Start here."
> git add -A; git commit -m "One"
> git add -A; git commit -m "Two"
> git add -A' git commit -m "Three"
> git log --oneline --graph -4 --decorate
> * da883dc (HEAD, master) Three
> * 92d3eb7 Two
> * c6e82d3 One
> * e1e8042 Start here.
> git reset --soft HEAD~3
> git log --oneline --graph -1 --decorate
> * e1e8042 Start here.
现在所有更改都会保留,并且可以作为一个更改提交。
这两个命令是否真的相同(reset --soft
vs commit --amend
)?
有任何理由在实践中使用其中一种吗?
commit --amend
从最后一次提交中添加/ rm文件或更改其消息。 reset --soft <commit>
将多个顺序提交合并为一个新提交。更重要的是,除了修改提交之外,reset --soft
还有其他用途吗?
答案 2 :(得分:16)
我用它来修改 last 提交。
假设我在提交A中犯了一个错误然后提交了B.现在我只能修改B.
所以我做git reset --soft HEAD^^
,我纠正并重新提交A,然后重新提交B.
当然,对于大型提交来说它不是很方便......但是你不应该做大量的提交; - )
答案 3 :(得分:9)
另一个潜在的用途是作为存储的替代方法(有些人不喜欢,例如https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/)。
例如,如果我在分支机构工作并需要在主人身上紧急修理某些事情,我可以这样做:
git commit -am "In progress."
然后结帐主人并进行修复。当我完成后,我会回到我的分支机构并做
git reset --soft HEAD~1
继续在我离开的地方工作。
答案 4 :(得分:6)
您可以使用git reset --soft
更改您希望拥有的版本,以便在索引和工作树中进行更改。有用的情况很少见。有时您可能会认为工作树中的更改应属于不同的分支。或者你可以使用它作为一种简单的方法将几个提交折叠成一个(类似于壁球/折叠)。
VonC的这个答案是一个实际的例子: Squash the first two commits in Git?
答案 5 :(得分:6)
一种可能的用法是当您想要在另一台机器上继续工作时。它会像这样工作:
以类似藏匿名称的方式签出新分支
git checkout -b <branchname>_stash
推送你的藏匿分支,
git push -u origin <branchname>_stash
切换到您的其他计算机。
拉下你的藏匿处和现有的分支,
git checkout <branchname>_stash; git checkout <branchname>
您现在应该在现有分支上。合并来自隐藏分支的更改
git merge <branchname>_stash
在合并之前将现有分支软复位为1,
git reset --soft HEAD^
删除您的藏匿分支
git branch -d <branchname>_stash
同时从原点删除您的隐藏分支
git push origin :<branchname>_stash
继续使用您的更改,就像您正常隐藏它们一样。
我认为,在未来,GitHub和co。应该用更少的步骤提供这种“远程藏匿”功能。
答案 6 :(得分:5)
使用“git reset --soft <sha1>
”的一个很好的理由是将HEAD
移到一个简单的仓库中。
如果您尝试使用--mixed
或--hard
选项,则会因为您尝试修改和处理不存在的树和/或索引而收到错误。
注意:您需要直接从裸仓库中执行此操作。
再次注意:您需要确保要在裸仓库中重置的分支是活动分支。如果没有,请按照VonC的answer了解如何在直接访问回购时更新裸仓库中的活动分支。
答案 7 :(得分:1)
SourceTree是一个git GUI,它有一个非常方便的界面,只需要暂存你想要的位。它没有任何类似的东西可以修改正确的版本。
因此git reset --soft HEAD~1
在此方案中比commit --amend
更有用。我可以撤消提交,将所有更改恢复到暂存区域,然后使用SourceTree继续调整暂存位。
实际上,在我看来,commit --amend
是两者中更冗余的命令,但是git是git,并且不会回避那些略有不同的命令。
答案 8 :(得分:0)
虽然我真的很喜欢此线程中的答案,但我使用git reset --soft
进行了稍有不同,但非常实用的情况。
我使用IDE进行开发,该IDE具有良好的差异工具,可显示上次提交后的更改(暂存和暂存)。现在,我的大部分任务都涉及多个提交。例如,假设我进行了5次提交以完成特定任务。在从1-5进行的每次增量提交期间,我都使用IDE中的diff工具查看从上一次提交所做的更改。我发现这是一种非常有用的方法,可以在提交之前查看我的更改。
但是,在我的任务结束时,当我想一起查看所有更改(在第一次提交之前)时,在发出请求之前进行自我代码审查,我只会看到上一次提交的更改(在提交4之后),并且不会从当前任务的所有提交中更改。
因此,我使用git reset --soft HEAD~4
返回4次提交。这使我可以一起查看所有更改。当我对自己的更改充满信心后,便可以进行git reset HEAD@{1}
并将其自信地推送到远程。
答案 9 :(得分:0)
另一个用例是,当您要在请求请求中用您的分支替换另一个分支时,例如,假设您在开发中拥有具有功能A,B,C的软件。
您正在开发下一个版本,并且您:
已删除功能B
添加了功能D
在此过程中,为功能B开发刚刚添加的修补程序。
您可以将开发合并到下一个,但是有时可能会很混乱,但是您也可以使用git reset --soft origin/develop
并使用所做的更改创建提交,分支可以合并而不会发生冲突并保留您的更改。
事实证明git reset --soft
是一个方便的命令。我个人经常使用它来压缩未完成“ WIP”之类的“完成工作”的提交,因此当我打开请求请求时,我的所有提交都是可以理解的。