Answers:
git reset与移动有关HEAD,通常是分支ref。
问题:工作树和索引如何?
当与使用--soft,移动HEAD,最常更新分支ref,将只HEAD。
这不同于commit --amend:
commit --amend仅允许不移动HEAD,同时允许重做当前提交)刚刚发现以下结合示例:
全部合并为一个(章鱼,因为合并了两个以上的分支),提交合并。
Tomas“ wereHamster” Carnecky在他的“ Subtree Octopus merge”文章中解释道:
- 如果要将一个项目合并到另一个项目的子目录中,则可以使用子树合并策略,并随后使该子项目保持最新状态。它是git子模块的替代。
- 章鱼合并策略可用于合并三个或更多分支。普通策略只能合并两个分支,如果您尝试合并多个分支,git会自动退回到章鱼策略。
问题是您只能选择一种策略。但是我想将两者结合起来以得到一个干净的历史记录,在该历史记录中,整个存储库都被自动更新为新版本。
我有一个超级项目,我们称它为
projectA一个子项目,projectB并合并到的子目录中projectA。
(这是子树合并部分)
我还在维护一些本地提交。
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
在这里,作者使用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
因此,每次:
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 --softvs commit --amend)?
有什么理由在实际中使用其中一个?
commit --amend 从最后一次提交中添加/ rm文件或更改其消息。 reset --soft <commit> 将几个顺序提交合并为一个新的提交。更重要的是,reset --soft除了修改提交,还有其他用途吗?
reset --soft除了修改提交还有其他用途-否”
git reset当您(a)想要重写历史记录,(b)不在乎旧的提交(这样可以避免交互式变基的麻烦),并且(c)具有多个更改承诺(否则,commit --amend更简单)。
我用它来修改的不仅仅是上一次提交。
假设我在提交A时犯了一个错误,然后在提交B中犯了错误。现在我只能修改git reset --soft HEAD^^B。
当然,对于大型提交不是很方便……但是无论如何您都不应该进行大型提交;-)
git commit --fixup HEAD^^ git rebase --autosquash HEAD~X效果也不错。
git rebase --interactive HEAD^^您可以在其中选择编辑提交A和B。以这种方式保留A和B的提交消息,如果需要,您仍然可以对其进行修改。
git reset A进行并添加更改git commit --amend,git cherry-pick <B-commit-hash>。
另一个潜在的用途是替代隐藏(有些人不喜欢,请参见例如https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/)。
例如,如果我在分支上工作,并且需要在master上紧急修复某些问题,我可以这样做:
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:)
您可以git reset --soft用来更改要作为索引和工作树中的更改的父版本。有用的情况很少见。有时,您可能会决定您在工作树中所做的更改应属于另一个分支。或者,您可以使用此方法作为将多个提交折叠为一个的简单方法(类似于压缩/折叠)。
参见VonC的答案,了解一个实际示例: 在Git中压入前两次提交?
git reset --soft anotherBranch然后在那提交?但是您实际上并没有更改ckeckout分支,因此您将提交到Branch还是anotherBranch吗?
一种可能的用法是当您想在另一台机器上继续工作时。它将像这样工作:
签出一个具有类似隐藏名称的新分支,
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。应该以更少的步骤提供此“远程隐藏”功能。
一种实际用途是,如果您已经提交了本地存储库(即git commit -m),则可以通过执行git reset --soft HEAD〜1来撤销最后一次提交
同样据您所知,如果您已经上演了更改(即使用git add),则可以通过执行git reset --mixed HEAD来逆转该阶段,或者我也经常使用过git reset
最后,git reset --hard清除所有内容,包括本地更改。〜后头告诉您从顶部开始有多少次提交。
git reset --soft HEAD ~1给了我fatal: Cannot do soft reset with paths.我认为我们需要在HEAD之后删除空格,而是git reset --soft HEAD~1
使用' git reset --soft <sha1>'的一个重要原因是进入HEAD裸仓库。
如果尝试使用--mixedor --hard选项,则将由于尝试修改和工作不存在的树和/或索引而收到错误消息。
注意:您将需要直接从裸仓库执行此操作。
再次注意:您将需要确保要在裸仓库中重置的分支是活动分支。如果没有,请直接访问仓库,按照VonC的答案在裸仓库中更新活动分支。
SourceTree是一个git GUI,它具有一个非常方便的界面,用于仅暂存所需的位。它没有任何类似的东西可以修改适当的修订版。
因此git reset --soft HEAD~1比commit --amend这种情况下有用得多。我可以撤消提交,将所有更改返回到暂存区域,然后继续使用SourceTree调整已暂存的位。
确实,在我看来,这commit --amend是两者中更冗余的命令,但是git是git,并且不会回避执行稍有不同的事情的类似命令。
虽然我真的很喜欢这个线程中的答案git reset --soft,但我使用的是稍微不同但非常实用的场景。
我使用IDE进行开发,该IDE具有良好的diff工具,用于显示上次提交后的更改(暂存和未暂存)。现在,我的大部分任务都涉及多个提交。例如,假设我进行了5次提交以完成特定任务。在从1-5进行的每次增量提交期间,我都使用IDE中的diff工具查看从上一次提交所做的更改。我发现这是一种非常有用的方法,可以在提交之前检查我的更改。
但是在我的任务结束时,当我想一起查看所有更改(从第一次提交之前)时,在发出拉取请求之前进行自我代码审查,我只会看到前一次提交(提交之后)的更改。 4)并不会因当前任务的所有提交而改变。
所以我git reset --soft HEAD~4经常返回4次提交。这使我可以一起查看所有更改。当我对自己的更改充满信心后,便可以git reset HEAD@{1}放心地将其推送到远程。
git add --patch,并git commit多次向建承诺,如果你知道你在这样做所有你已经构建系列。您的第一批提交就像您桌上的便笺或备忘录的初稿一样,它们是在组织您的想法,而不是用于发布。
git reset @{1}还原第一个草稿系列,而是可以通过git add -p和构建一个for-publication系列git commit。
另一个用例是,当您要在请求请求中用您的分支替换另一个分支时,例如,假设您在开发中具有功能A,B,C的软件。
您正在使用下一版本进行开发,并且您:
删除了功能B
新增功能D
在此过程中,为功能B开发刚刚添加的修补程序。
您可以将开发合并到下一个,但是有时可能会很混乱,但是您也可以使用git reset --soft origin/develop更改创建并提交,分支可以合并而不会发生冲突并保留您的更改。
事实证明,这git reset --soft是一个方便的命令。我个人经常使用它来压缩未完成“ WIP”之类的“完成工作”的提交,因此当我打开请求请求时,我的所有提交都是可以理解的。
git reset --soft:stackoverflow.com/questions/6869705/…–