git reset --soft 的实际用途?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5203535/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Practical uses of git reset --soft?
提问by AJJ
I have been working with git for just over a month. Indeed I have used reset for the first time only yesterday, but the soft reset still doesn't make much sense to me.
我已经使用 git 一个多月了。确实我昨天才第一次使用reset,但是软复位对我来说仍然没有多大意义。
I understand I can use the soft reset to edit a commit without altering the index or the working directory, as I would with git commit --amend
.
我知道我可以使用软重置来编辑提交而无需更改索引或工作目录,就像使用git commit --amend
.
Are these two commands really the same (reset --soft
vs commit --amend
)? Any reason to use one or the other in practical terms? And more importantly, are there any other uses for reset --soft
apart from amending a commit?
这两个命令真的一样吗(reset --soft
vs commit --amend
)?有什么理由在实际中使用其中之一吗?更重要的是,reset --soft
除了修改提交之外,还有其他用途吗?
采纳答案by VonC
git reset
is all about moving HEAD
, and generally the branch ref.
Question: what about the working tree and index?
When employed with --soft
, moves HEAD
, most often updating the branch ref, and only the HEAD
.
This differ from commit --amend
as:
git reset
都是关于移动的HEAD
,通常是分支ref。
问题:工作树和索引怎么样?
与 一起使用时--soft
,移动时HEAD
,最常更新分支引用,并且仅更新HEAD
.
这不同于commit --amend
:
- it doesn't create a new commit.
- it can actually move HEAD to any commit (as
commit --amend
is only about notmoving HEAD, while allowing to redo the current commit)
- 它不会创建新的提交。
- 它实际上可以将 HEAD 移动到任何提交(
commit --amend
只是不移动 HEAD,同时允许重做当前提交)
Just found this example of combining:
刚刚发现这个组合的例子:
- a classic merge
- a subtree merge
- 经典的合并
- 子树合并
all into one (octopus, since there is more than two branches merged) commit merge.
全部合二为一(章鱼,因为合并了两个以上的分支)提交合并。
Tomas "wereHamster" Carneckyexplains in his "Subtree Octopus merge" article:
Tomas “wereHamster” Carnecky在他的“Subtree Octopus merge”文章中解释道:
- The subtree merge strategy can be used if you want to merge one project into a subdirectory of another project, and the subsequently keep the subproject up to date. It is an alternative to git submodules.
- The octopus merge strategy can be used to merge three or more branches. The normal strategy can merge only two branches and if you try to merge more than that, git automatically falls back to the octopus strategy.
The problem is that you can choose only one strategy. But I wanted to combine the two in order to get a clean history in which the whole repository is atomically updated to a new version.
I have a superproject, let's call it
projectA
, and a subproject,projectB
, that I merged into a subdirectory ofprojectA
.
- 如果您想将一个项目合并到另一个项目的子目录中,并且随后使子项目保持最新,则可以使用子树合并策略。它是 git 子模块的替代品。
- 章鱼合并策略可用于合并三个或更多分支。正常的策略只能合并两个分支,如果您尝试合并的分支超过两个,git 会自动回退到章鱼策略。
问题是您只能选择一种策略。但我想将两者结合起来,以获得一个干净的历史记录,其中整个存储库自动更新到新版本。
我有一个超级项目,我们称之为
projectA
,还有一个子项目,projectB
我合并到projectA
.
(that's the subtree merge part)
(那是子树合并部分)
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:
我也在维护一些本地提交。
ProjectA
定期更新,projectB
每隔几天或几周就有一个新版本,通常取决于projectA
.当我决定更新这两个项目时,我不会简单地拉取
projectA
,projectB
因为这会为整个项目的原子更新创建两次提交。
相反,我创建了一个合并提交,它结合了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
Here the author used a reset --hard
, and then read-tree
to restore what the first two merges had done to the working tree and index, but that is where reset --soft
can help:
How to I redo those two merges, which have worked, i.e. my working tree and index are fine, but without having to record those two commits?
在这里,作者使用了reset --hard
, 然后read-tree
恢复前两次合并对工作树和索引所做的工作,但这就是reset --soft
可以提供帮助的地方:
如何重做这两个合并,它们已经工作,即我的工作树和索引是很好,但不必记录这两个提交?
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
Now, we can resume Tomas's solution:
现在,我们可以恢复 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
So, each time:
所以,每次:
- you are satisfied with what you end up with (in term of working tree and index)
- you are notsatisfied with all the commits that took you to get there:
- 您对最终结果感到满意(就工作树和索引而言)
- 你是不是满意,所有的带你到那里的提交:
git reset --soft
is the answer.
git reset --soft
是答案。
回答by Shaun Luttin
Use Case - Combine a series of local commits
用例 - 组合一系列本地提交
"Oops. Those three commits could be just one."
“糟糕。这三个提交可能只是一个。”
So, undo the last 3 (or whatever) commits (without affecting the index nor working directory). Then commit all the changes as one.
因此,撤消最后 3 次(或其他)提交(不影响索引或工作目录)。然后将所有更改提交为一个。
E.g.
例如
> 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.
Now all your changes are preserved and ready to be committed as one.
现在您的所有更改都被保留并准备好作为一个整体提交。
Short answers to your questions
简短回答您的问题
Are these two commands really the same (reset --soft
vs commit --amend
)?
这两个命令真的一样吗(reset --soft
vs commit --amend
)?
- No.
- 不。
Any reason to use one or the other in practical terms?
有什么理由在实际中使用其中之一吗?
commit --amend
to add/rm files from the very last commit or to change its message.reset --soft <commit>
to combine several sequential commits into a new one.
commit --amend
从最后一次提交添加/rm 文件或更改其消息。reset --soft <commit>
将几个连续的提交组合成一个新的提交。
And more importantly, are there any other uses for reset --soft
apart from amending a commit?
更重要的是,reset --soft
除了修改提交之外,还有其他用途吗?
- See other answers :)
- 查看其他答案:)
回答by Simon
I use it to amend more than just the lastcommit.
我用它来修改不仅仅是最后一次提交。
Let's say I made a mistake in commit A and then made commit B. Now I can only amend B.
So I do git reset --soft HEAD^^
, I correct and re-commit A and then re-commit B.
假设我在提交 A 中犯了一个错误,然后提交了 B。现在我只能修改 B。所以我这样做了git reset --soft HEAD^^
,我纠正并重新提交 A,然后重新提交 B。
Of course, it's not very convenient for large commits… but you shouldn't do large commits anyway ;-)
当然,对于大的提交来说不是很方便……但是无论如何你都不应该做大的提交 ;-)
回答by deltacrux
Another potential use is as an alternative to stashing (which some people don't like, see e.g. https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/).
另一个潜在用途是作为隐藏的替代品(有些人不喜欢,例如https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-thinked-harmful/)。
For example, if I'm working on a branch and need to fix something urgently on master, I can just do:
例如,如果我在一个分支上工作并且需要在 master 上紧急修复某些东西,我可以这样做:
git commit -am "In progress."
then checkout master and do the fix. When I'm done, I return to my branch and do
然后结帐大师并进行修复。完成后,我返回我的分支并执行
git reset --soft HEAD~1
to continue working where I left off.
在我离开的地方继续工作。
回答by j2emanue
One practical use is if you have committed to your local repo already (ie. git commit -m ) then you can reverse that last commit by doing git reset --soft HEAD~1
一个实际用途是,如果您已经提交到本地存储库(即 git commit -m ),那么您可以通过执行git reset --soft HEAD~1来反转最后一次提交
Also for your knowledge, if you have staged your changes already (ie with git add .) then you can reverse the staging by doing git reset --mixed HEADor i've commonly also just used git reset
另外,为了您的知识,如果您已经暂存了您的更改(即使用 git add 。)那么您可以通过执行git reset --mixed HEAD或我通常也刚刚使用来反转暂存git reset
lastly, git reset --hardwipes everything out including your local changes. The ~ after head tells you how many commits to go to from the top.
最后,git reset --hard清除所有内容,包括您的本地更改。head 后面的 ~ 告诉你从顶部到多少次提交。
回答by Johannes Rudolph
You can use git reset --soft
to change the version you want to have as parent for the changes you have in your index and working tree. The cases where this is useful are rare. Sometimes you might decide that the changes you have in your working tree should belong onto a different branch. Or you can use this as a simple way to collapse several commits into one (similar to squash/fold).
git reset --soft
对于索引和工作树中的更改,您可以使用更改要作为父级的版本。这很有用的情况很少见。有时您可能会决定您在工作树中所做的更改应该属于不同的分支。或者您可以将其用作将多个提交折叠为一个的简单方法(类似于压缩/折叠)。
See this answer by VonC for a practical example: Squash the first two commits in Git?
有关实际示例,请参阅 VonC 的这个答案: Squash the first two commits in Git?
回答by llaughlin
One possible usage would be when you want to continue your work on a different machine. It would work like this:
一种可能的用法是当您想在另一台机器上继续工作时。它会像这样工作:
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.
签出一个具有类似 stash 名称的新分支,
git checkout -b <branchname>_stash
把你的藏匿处推上去,
git push -u origin <branchname>_stash
切换到另一台机器。
拉下你的藏匿处和现有的分支,
git checkout <branchname>_stash; git checkout <branchname>
你现在应该在你现有的分支上。合并来自 stash 分支的更改,
git merge <branchname>_stash
在合并之前将现有分支软重置为 1,
git reset --soft HEAD^
删除你的藏匿分支,
git branch -d <branchname>_stash
还要从原点删除你的藏匿分支,
git push origin :<branchname>_stash
继续处理您的更改,就像您已正常隐藏它们一样。
I think, in the future, GitHub and co. should offer this "remote stash" functionality in fewer steps.
我认为,在未来,GitHub 和 co. 应该以更少的步骤提供这种“远程存储”功能。
回答by Hazok
A great reason to use 'git reset --soft <sha1>
' is to move HEAD
in a bare repo.
使用 ' git reset --soft <sha1>
' 的一个重要原因是移动HEAD
到一个裸仓库中。
If you try to use the --mixed
or --hard
option, you'll get an error since you're trying to modify and working tree and/or index that does not exist.
如果您尝试使用--mixed
or--hard
选项,您将收到错误消息,因为您正在尝试修改和工作不存在的树和/或索引。
Note: You will need to do this directly from the bare repo.
注意:您需要直接从裸仓库执行此操作。
Note Again: You will need to make sure the branch you want to reset in the bare repo is the active branch. If not, follow VonC's answeron how to update the active branch in a bare repo when you have direct access to the repo.
再次注意:您需要确保要在裸仓库中重置的分支是活动分支。如果没有,请按照 VonC 的回答了解如何在您可以直接访问存储库时更新裸存储库中的活动分支。
回答by Roman Starkov
SourceTree is a git GUI which has a pretty convenient interface for staging just the bits you want. It does not have anything remotely similar for amending a proper revision.
SourceTree 是一个 git GUI,它有一个非常方便的界面来暂存你想要的位。它没有任何类似的东西可以修改适当的修订版。
So git reset --soft HEAD~1
is much more useful than commit --amend
in this scenario. I can undo the commit, get all the changes back into the staging area, and resume tweaking the staged bits using SourceTree.
Sogit reset --soft HEAD~1
比commit --amend
在这种情况下有用得多。我可以撤消提交,将所有更改返回到暂存区,然后使用 SourceTree 继续调整暂存位。
Really, it seems to me that commit --amend
is the more redundant command of the two, but git is git and does not shy away from similar commands that do slightly different things.
真的,在我看来,这commit --amend
是两者中更冗余的命令,但 git 是 git,并且不会回避执行略有不同的类似命令。
回答by Swanky Coder
While I really like the answers in this thread, I use git reset --soft
for a slightly different, but a very practical scenario nevertheless.
虽然我真的很喜欢这个线程中的答案git reset --soft
,但我仍然使用了一个略有不同但非常实用的场景。
I use an IDE for development which has a good diff tool for showing changes (staged and unstaged) after my last commit. Now, most of my tasks involve multiple commits. For example, let's say I make 5 commits to complete a particular task. I use the diff tool in the IDE during every incremental commit from 1-5 to look at my changes from the last commit. I find it a very helpful way to review my changes before committing.
我使用 IDE 进行开发,它有一个很好的 diff 工具,用于显示我上次提交后的更改(暂存和未暂存)。现在,我的大部分任务都涉及多次提交。例如,假设我进行了 5 次提交以完成特定任务。在从 1 到 5 的每次增量提交期间,我都使用 IDE 中的 diff 工具来查看上次提交的更改。我发现这是一种在提交之前检查更改的非常有用的方法。
But at the end of my task, when I want to see all my changes together (from before 1st commit), to do a self code-review before making a pull request, I would only see the changes from my previous commit (after commit 4) and not changes from all the commits of my current task.
但是在我的任务结束时,当我想一起查看我的所有更改(从第一次提交之前),在提出拉取请求之前进行自我代码时,我只会看到我之前提交的更改(提交之后) 4) 而不是我当前任务的所有提交的变化。
So I use git reset --soft HEAD~4
to go back 4 commits. This lets me see all the changes together. When I am confident of my changes, I can then do git reset HEAD@{1}
and push it to remote confidently.
所以我使用git reset --soft HEAD~4
返回 4 次提交。这让我可以一起看到所有的变化。当我对我的更改充满信心时,我就可以git reset HEAD@{1}
自信地将其推送到远程。