git 删除合并提交,保留当前更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21115596/
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
Remove a merge commit, keeping current changes
提问by khose
We have had a small problem in our team. One dev had to include some changes in our development branch. Before doing so, he accidentally merged a feature branch (which shouldn't be merged then) and kept on working over those changes, generating a couple of commits after the merge.
我们的团队遇到了一个小问题。一位开发人员必须在我们的开发分支中包含一些更改。在这样做之前,他不小心合并了一个功能分支(当时不应该合并)并继续处理这些更改,在合并后生成了几次提交。
Now we want to keep those changes, but apply them to the commit before the merge was done. To keep it clear:
现在我们想保留这些更改,但在合并完成之前将它们应用到提交。为清楚起见:
A (+b, +a)
|
B (+a)
|
C (merge commit)
|\
D \
| E (feature branch)
| /
|/
F
What we want to have his changes (+a,+b)applied over commit D. The equivalent to:
我们希望他的更改(+a,+b)应用于提交D。相当于:
C (+a,+b)
|
D
| E (feature branch)
| /
|/
F
How can we commit a change to dismiss a previous merge keeping local changes?
我们如何提交更改以关闭先前的合并并保留本地更改?
采纳答案by Ash Wilson
This is a job for git rebase -i
. Run:
这是一份工作git rebase -i
。跑:
git rebase -i F
You'll be presented with a list of commits in ${EDITOR}
, like so:
您将看到 中的提交列表${EDITOR}
,如下所示:
pick 334ad92 D
pick fb54c42 E
pick 6901e51 B
pick 6c61a52 A
# Rebase eea2847..6c61a52 onto eea2847
#
# (more instructions here)
Delete the pick fb54c42 E
line to remove that commit. (Also, if you want A
and B
to be combined into a single commit, you can change the pick
command to squash
-- squash 6c61a52 A
). Save and close the file and your branches will be in the state you wish.
删除该pick fb54c42 E
行以删除该提交。(此外,如果您想将A
和B
合并为一个提交,您可以将pick
命令更改为squash
-- squash 6c61a52 A
)。保存并关闭文件,您的分支将处于您希望的状态。
Note that this will change history. This means that you'll need to do a git push -f
if you've already pushed the branch anywhere, and it'll mess with anyone else who's been collaborating on this branch. If that's an issue, you can git revert
the merge commit instead:
请注意,这将改变历史。这意味着git push -f
如果您已经将分支推送到任何地方,则需要执行 a ,并且它会与在该分支上进行协作的其他任何人混淆。如果这是一个问题,您可以git revert
改为合并提交:
git revert -m 1 C
The -m 1
argument tells git to revert against the first parent of the commit, which is the side that was merged into (D
, in your diagram).
该-m 1
参数告诉 git 恢复提交的第一个父项,即合并到 ( D
, 在您的图中)的一侧。
回答by kostix
I fail to understand what direction the timeline has in your examples (which commits are made before which) so I'll explain in broad terms:
我无法理解时间线在您的示例中的方向(哪些提交是在哪些之前进行的),因此我将进行广泛的解释:
- Fork a new branch off the pre-merge commit, and check it out.
git cherry-pick A
andB
there to bring in the changes made by the deveoper in a merge commit.- Cherry-pick whatever commits came after the merge commit.
- 从合并前的提交中分出一个新分支,并检查它。
git cherry-pick A
并B
在那里引入开发人员在合并提交中所做的更改。- Cherry-pick 合并提交之后的任何提交。
By now your new branch contains the history as it supposed to look at so you might now git reset --hard
your original branch to this state. Be aware that force-pushing it to a shared repository and fetching it by the other devs will have obvious repercussions for them: everyone will have to git rebase
whatever work they have based on the old state of that branch to its new state.
到现在为止,您的新分支包含它应该查看的历史记录,因此您现在可以git reset --hard
将原始分支转到此状态。请注意,将其强制推送到共享存储库并由其他开发人员获取将对他们产生明显的影响:每个人都git rebase
必须根据该分支的旧状态将他们所做的任何工作转换为新状态。
You might also want to "refork" the feature branch off the "fixed" branch. As I've said, I failed to see whether it was forked before the offending commit of after. If it was done before, you won't need fixing up the feature branch.
您可能还想从“固定”分支“重新分叉”功能分支。正如我所说,我没有看到它是否在 after 的违规提交之前分叉。如果之前完成,则不需要修复功能分支。
回答by Magnus B?ck
Use git revert C
to revert the C merge commit (you may have to pass -m 1
so that Git knows which side of the merge to keep). See How to revert a faulty mergefor details and an elaboration of what happens if you continue work on the feature branch and later on decide to merge it again.
使用git revert C
恢复的C合并提交(您可能要通过-m 1
让Git的知道,以保持其合并的一侧)。请参阅如何恢复错误的合并以获取详细信息,并详细说明如果您继续在功能分支上工作然后决定再次合并它会发生什么。
The revert approach doesn't give you exactly what you're asking for; the commits brought in by the merge will still be part of the project's history, but their changes will be gone. Getting rid of the commits and the merge altogether will require a rebase (and described in Ash Wilson's response), which requires careful consideration and usually isn't worth the effort unless there are legal restrictions or technical issues (like gigantic binaries) with the commits that arrived through the merge commit.
恢复方法并没有完全满足您的要求;合并带来的提交仍将是项目历史的一部分,但它们的更改将消失。完全摆脱提交和合并将需要重新设定基准(并在 Ash Wilson 的回应中进行了描述),这需要仔细考虑并且通常不值得付出努力,除非提交存在法律限制或技术问题(如巨大的二进制文件)通过合并提交到达。
回答by pampi
If you had a local repository rather than remote repository, it would have been easy.
如果您有一个本地存储库而不是远程存储库,那就很容易了。
local
当地的
- feature-branch - updated with broken/improper commit *
- master - merged
- 功能分支 - 更新损坏/不正确的提交 *
- 主合并
remote
偏僻的
- feature-branch - updated
- master - not-merged
- 功能分支 - 更新
- 主 - 未合并
if this is the scenario, you just have to delete both local feature-branch and master, then get/checkout from the remote repository.
如果是这种情况,您只需删除本地功能分支和主分支,然后从远程存储库获取/签出。
Hope it still helps. :)
希望它仍然有帮助。:)