我已经使用Git一个月多了。事实上,我昨天才第一次使用reset,但是软重置对我来说仍然不太清楚。
我知道可以使用软重置来编辑提交记录而不改变索引或工作目录,就像我使用 git commit --amend
命令一样。
这两个命令真的一样吗(reset --soft
vs commit --amend
)?在实际应用中使用它们有什么理由?更重要的是,除了修改提交记录之外,reset --soft
还有其他用途吗?
我已经使用Git一个月多了。事实上,我昨天才第一次使用reset,但是软重置对我来说仍然不太清楚。
我知道可以使用软重置来编辑提交记录而不改变索引或工作目录,就像我使用 git commit --amend
命令一样。
这两个命令真的一样吗(reset --soft
vs commit --amend
)?在实际应用中使用它们有什么理由?更重要的是,除了修改提交记录之外,reset --soft
还有其他用途吗?
git reset
主要是关于移动HEAD
,通常也会更新分支ref。
问题:那工作树和索引呢?
当使用--soft
时,它会移动HEAD
,通常也会更新分支ref,但只会影响HEAD
。
这与commit --amend
不同的地方在于:
HEAD
移动到任何提交(而commit --amend
只是关于不移动HEAD
,同时允许重新做当前提交)刚刚找到这个合并的例子:
全部合并成一个(章鱼式,因为合并了两个以上的分支)提交合并。
Tomas "wereHamster" Carnecky 在他的"Subtree Octopus merge" 文章中解释:
- 如果你想将一个项目合并到另一个项目的子目录中,并且随后保持子项目与主项目同步,可以使用子树合并策略。它是 git 子模块的替代方案。
projectA
,还有一个子项目projectB
,我将其合并到了projectA
的一个子目录中。I'm also maintaining a few local commits.
ProjectA
is regularly updated,projectB
has a new version every couple days or weeks and usually depends on a particular version ofprojectA
.When I decide to update both projects, I don't simply pull from
projectA
andprojectB
as that would create two commits for what should be an atomic update of the whole project.
Instead, I create a single merge commit which combinesprojectA
,projectB
and my local commits.
The tricky part here is that this is an octopus merge (three heads), butprojectB
needs to be merged with the subtree strategy. So this is what I do:
# 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
可以帮助的地方:
我如何重新执行那两次已经完成的合并,即我的工作树和索引正常,但不必记录那两个提交?
# 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
--no-soft
没有意义,Git 2.42(2023年第三季度)现在会告诉你。gitster
)提交。gitster
--在commit e672bc4中合并,2023年7月27日)
e672bc4f76
:合并分支'jc/parse-options-reset'--no-(mixed|soft|hard|merge|keep)
选项"哎呀,这三个提交可以合并成一个。"
因此,撤销最近的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
用于在最后一个提交中添加/移除文件或更改其消息。reset --soft <commit>
用于将几个连续的提交合并成一个新提交。更重要的是,reset --soft
还有其他用途吗?
reset --soft
?- 没有。 - Antony Hatchkinsgit reset
)在以下情况下很好:(a)想要重写历史记录,(b)不关心旧提交(因此可以避免交互式变基的麻烦),以及(c)有多个提交要更改(否则,commit --amend
更简单)。 - johncip我使用它来修改的不仅是最后一次提交。
假设我在提交A时犯了一个错误,然后又提交了B。现在我只能修改B。
所以我执行 git reset --soft HEAD^^
,我更正并重新提交A,然后再次提交B。
当然,对于大型提交来说这不是很方便...但通常你也不应该做太大的提交。
git commit --fixup HEAD^^
的意思是“创建一个修正上上个提交的修正提交”。
git rebase --autosquash HEAD~X
也能够很好地工作。它的作用是将当前分支与 HEAD 向前 X 次提交进行交互式重写,同时自动压缩以前使用 git commit --fixup
创建的修正提交。 - Niklasgit rebase --interactive HEAD^^
命令。这种方式保留了提交记录 A 和 B 的提交信息,如果需要的话,您仍然可以修改它们。 - Paul Pladijsgit reset A
,进行更改并添加,git commit --amend
,git cherry-pick <B-commit-hash>
。 - naught101另一个潜在的用途是作为代替git stash(有些人不喜欢,例如参见https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/)的选择。
例如,如果我正在某个分支上工作,需要紧急修复主分支上的问题,我只需执行:
git commit -am "In progress."
然后检查主分支并进行修复。当我完成后,返回到我的分支并执行
git reset --soft HEAD~1
继续在我离开的地方工作。
--soft
在这里实际上是不必要的,除非你真的关心改变立即被暂存。现在我只用 git reset HEAD~
就可以了。如果我需要切换分支并希望保持一些更改已经被暂存,那么我会执行 git commit -m "staged changes"
,然后 git commit -am "unstaged changes"
,之后再执行 git reset HEAD~
并跟着执行 git reset --soft HEAD~
来完全恢复工作状态。虽然,老实说,现在我知道了 git-worktree
,这些事情我做得少多了 :) - deltacrux一个实用的用途是,如果你已经提交到你的本地仓库了(例如,git commit -m),那么你可以通过执行git reset --soft HEAD~1来撤销最后一次提交。
此外,需要提醒您的是,如果您已经暂存了更改内容(例如,使用git add .),那么您可以通过执行git reset --mixed HEAD来撤销暂存,或者通常也可以使用git reset
。
最后,git reset --hard会清除所有东西,包括您的本地更改。在head后面的“~”告诉您要从顶部退回多少次提交。
git reset --soft HEAD ~1
gives me fatal: Cannot do soft reset with paths.
I think we need to remove the space after HEAD so it would be git reset --soft HEAD~1
- Andrew Lohr一种可能的用途是在您想要在另一台机器上继续工作时使用。它将按照以下方式工作:
Checkout a new branch with a stash-like name,
git checkout -b <branchname>_stash
Push your stash branch up,
git push -u origin <branchname>_stash
Switch to your other machine.
Pull down both your stash and existing branches,
git checkout <branchname>_stash; git checkout <branchname>
You should be on your existing branch now. Merge in the changes from the stash branch,
git merge <branchname>_stash
Soft reset your existing branch to 1 before your merge,
git reset --soft HEAD^
Remove your stash branch,
git branch -d <branchname>_stash
Also remove your stash branch from origin,
git push origin :<branchname>_stash
Continue working with your changes as if you had stashed them normally.
git reset --soft <sha1>
”的一个很好的理由是将HEAD
移动到裸仓库中。如果尝试使用--mixed
或--hard
选项,将会出现错误,因为您正在尝试修改不存在的工作树和/或索引。git reset --soft
来改变您想要作为父级的版本,用于对索引和工作树中的更改进行更改。这种情况很少发生。有时候您可能会决定将工作树中的更改放到另一个分支上。或者您可以使用它来将几个提交折叠成一个(类似于挤压/折叠)。git reset --soft anotherBranch
,然后在那里commit?但你并没有真正改变checkout branch,所以你会commit到_Branch_还是_anotherBranch_? - AJJgit reset --soft
的使用略有不同,但是在实际场景中仍然非常实用。git reset --soft HEAD~4
回到4次提交之前。这样我就可以看到所有的更改。当我确信我的更改后,我就可以使用git reset HEAD@{1}
并自信地将其推送到远程仓库。git add --patch
和 git commit
命令,以构建提交系列,就像您一直知道自己在做什么一样。您的第一个提交就像桌子上的笔记或备忘录的第一稿,它们是为了组织您的思路,而不是用于发布。 - jthillgit add -p
和 git commit
构建一个发布系列,而不是执行 git reset @{1}
来恢复您的初稿系列。 - jthill
git reset --soft
进行压缩的简单示例:https://dev59.com/cWw15IYBdhLWcg3wCnQn - VonC