git reset的实际用法–soft?

我一直在使用git一个多月。 事实上,我昨天才第一次使用了复位function,但软复位对我来说依然没有什么意义。

我知道我可以使用软重置编辑提交而不改变索引或工作目录,因为我会用git commit --amend

这两个命令是否真的一样( reset --soft vs commit --amend )? 任何理由使用这一个或另一个实际条件? 更重要的是,除了修改一个提交之外,是否还有其他的用途来reset --soft

git reset是关于移动HEAD
问题:工作树和索引怎么样?
当使用 – --soft移动HEAD ,只有头
这不同于commit --amend

  • 它不会创build一个新的提交。
  • 它实际上可以将HEAD移动到任何提交(因为commit --amend只是关于移动HEAD,而允许重做当前的提交)

刚刚find这个结合的例子:

  • 一个经典的合并
  • 一个子树合并

全部合为一体(章鱼,因为有两个以上的分支合并)提交合并。

Tomas“被仓鼠”Carnecky在他的“Subtree Octopus合并”一文中解释道 :

  • 如果要将一个项目合并到另一个项目的子目录中,并且随后保持该子项目处于最新状态,则可以使用子树合并策略。 这是git子模块的替代scheme。
  • 章鱼合并策略可以用来合并三个或更多分支。 正常的战略可以合并只有两个分支,如果你尝试合并更多的,git自动回落到章鱼战略。

问题是你只能select一种策略。 但是我想把两者结合起来,以便得到一个清晰的历史logging,在这个历史logging中,整个存储库都被primefaces更新为新版本。

我有一个超级项目,我们称之为projectA ,然后是一个子项目projectB ,它被合并到projectA的子目录中。

(这是子树合并部分)

我也维护一些本地提交。
ProjectA定期更新, projectB每隔几天或几周都有一个新版本,通常取决于projectA的特定版本。

当我决定更新这两个项目时,我不会简单地从projectAprojectB拉出来, 因为这会为整个项目的primefaces更新创build两个提交
相反, 我创build了一个合并提交,它结合了projectAprojectB和我的本地提交
这里棘手的部分是这是一个章鱼合并(三头), 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可以提供帮助的地方:
如何重做这两个合并 ,这是工作,即我的工作树和索引是好的,但不必logging这两个提交?

 # Move the HEAD, and just the HEAD, two commits back! git reset --soft HEAD@{2} 

现在,我们可以恢复Tomas的解决scheme:

 # 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是答案。

用例 – 结合一系列本地提交

“哎呀,这三个承诺可能只是一个。”

所以,撤销最后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

  • 查看其他答案:)

我用它来修改不止是最后一次提交。

假设我在提交A时犯了一个错误,然后提交了B.现在我只能修改B.所以我做了git reset --soft HEAD^^ ,我纠正并重新提交A,然后重新提交B.

当然,对于大型提交来说并不是很方便,但是不pipe怎样,你都不应该做大提交;-)

您可以使用git reset --soft来更改您希望作为父索引的版本,以适应您在索引和工作树中git reset --soft的更改。 这是有用的情况是罕见的。 有时你可能会认为在工作树中所做的更改应该属于不同的分支。 或者你可以使用这个方法将多个提交合并为一个(类似于squash / fold)。

VonC看到这个答案是一个实际的例子: 在Git中压缩前两个提交?

使用' git reset --soft <sha1> '的一个很好的理由是将HEAD移动到裸露的回购站中。

如果您尝试使用--mixed--hard选项,则会尝试修改并使用不存在的树和/或索引,因此会出现错误。

注意:您将需要直接从裸回购做到这一点。

再次注意:您将需要确保您想要在裸回购重置的分支是活动的分支。 如果没有,请按照VonC关于如何在直接访问回购时更新裸回购中的活动分支的回答 。

一种可能的用法是当你想在另一台机器上继续工作时。 它会这样工作:

  1. 签出一个存储类似名称的新分支,

     git checkout -b <branchname>_stash 
  2. 把你的储藏分支拉起来,

     git push -u origin <branchname>_stash 
  3. 切换到其他机器。

  4. 拉下你的藏匿处和现有的分支,

     git checkout <branchname>_stash; git checkout <branchname> 
  5. 你现在应该在你现有的分支上。 合并来自存储分支的更改,

     git merge <branchname>_stash 
  6. 在合并之前,将现有分支软件重置为1,

     git reset --soft HEAD^ 
  7. 删除你的存储分支,

     git branch -d <branchname>_stash 
  8. 同时删除你的存储分支从原点,

     git push origin :<branchname>_stash 
  9. 继续处理您的更改,就好像您正常保存了一样。

我想,在未来,GitHub和co。 应该以更less的步骤提供这种“远程存储”function。

另一个潜在的用途是作为替代存储(有些人不喜欢,见https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/ )。

例如,如果我在分支上工作,需要在主人身上紧急解决问题,我可以这样做:

 git commit -am "In progress." 

然后结帐主,并修复。 当我完成后,我回到我的分支去做

 git reset --soft HEAD~1 

继续工作,我离开了。

一个实际的用法是,如果你已经承诺你的本地回购(即git commit -m),那么你可以通过做git reset –soft HEAD〜1

另外对于你的知识,如果你已经上演你的变化(即使用git add),那么你可以通过做git reset –mixed HEAD

最后, git reset –hard把所有东西都抹掉 ,包括你本地的变化。 头后的数字告诉你从顶端开始有多less提交。

SourceTree是一个git GUI,它有一个非常方便的界面,用于分级你想要的位。 它没有任何类似的修改正确的修订。

所以在这种情况下, git reset --soft HEAD~1commit --amend更有用。 我可以撤销提交,将所有更改恢复到暂存区域,然后使用SourceTree继续调整暂存的位。

实际上,在我看来, commit --amend是更为多余的两个命令,但是git是git,并且不会回避类似的命令,它们做的事情稍有不同。