git - 合并时跳过特定提交

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/727994/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:18:56  来源:igfitidea点击:

git - skipping specific commits when merging

gitversion-control

提问by Brad Robinson

I've been using Git for about a year now and think it's fantastic, but I've just started on a second version of the project and started a new branch for it. I'm struggling a little with the best way to handle things going forward.

我已经使用 Git 大约一年了,我认为它很棒,但我刚刚开始了该项目的第二个版本,并为其创建了一个新分支。我正在努力寻找处理未来事情的最佳方式。

I have two branches called say master10 (for v1) and master20 (for v2). I've been making bug fixes in v1 on branch master10, and developing new stuff of master20. Whenever I make a bug fix I merge it into v2 by checking out master20 and doing git merge master10. So far so good.

我有两个分支,分别称为 master10(对于 v1)和 master20(对于 v2)。我一直在分支 master10 上的 v1 中修复错误,并开发 master20 的新东西。每当我修复错误时,我都会通过检查 master20 并执行git merge master10. 到现在为止还挺好。

Now however, I've made a change in v1 that I don't want in v2, but I want to continue merging other bug fixes. How do I tell Git to skip that particular commit (or a range of commits), but that going forward I still want to merge other bug fixes.

但是,现在我在 v1 中做了一些我不想在 v2 中进行的更改,但我想继续合并其他错误修复。我如何告诉 Git 跳过该特定提交(或一系列提交),但在此之前我仍然想合并其他错误修复。

I thought git rebasemight be what I need but read the doc and my head nearly exploded.

我想这git rebase可能是我需要的,但读了文档,我的头几乎要爆炸了。

I think what I want is something like a "git sync" command that tells git that two branches are now in-sync and in future only merge the commits from this sync-point on.

我想我想要的是类似于“git sync”命令的东西,它告诉 git 两个分支现在是同步的,并且将来只合并来自这个同步点的提交。

Any help appreciated.

任何帮助表示赞赏。

回答by araqnid

If you want to merge most but not all of the commits on branch "maint" to "master", for instance, you can do this. It requires some work---- as mentioned above, the usual use case is to merge everything from a branch--- but sometimes it happens that you made a change to a release version that shouldn't be integrated back (maybe that code's been superceded in master already), so how do you represent that? Here goes...

例如,如果您想将分支“maint”上的大部分但不是全部提交合并到“master”,您可以这样做。它需要一些工作----如上所述,通常的用例是合并分支中的所有内容---但有时会发生您对不应集成回来的发布版本进行了更改(也许该代码的已经在 master 中被取代),那么你如何表示呢?开始...

So let's suppose maint has had 5 changes applied, and one of those (maint~3) is not to be merged back into master, although all the others should be. You do this in three stages: actually merge everything before that one, tell git to mark maint~3 as merged even when it isn't, and then merge the rest. The magic is:

所以让我们假设 maint 已经应用了 5 个更改,其中一个 (maint~3) 不会合并回 master,尽管所有其他更改都应该合并。您分三个阶段执行此操作:实际上合并之前的所有内容,告诉 git 将 maint~3 标记为已合并,即使它没有合并,然后合并其余部分。魔术是:

bash <master>$ git merge maint~4
bash <master>$ git merge -s ours maint~3
bash <master>$ git merge maint

The first command merges everything beforeyour troublesome maint commit onto master. The default merge log message will explain you're merging "branch 'maint' (early part)".

第一个命令麻烦的维护提交到 master之前合并所有内容。默认合并日志消息将解释您正在合并“分支‘维护’(早期)”。

The second command merges the troublesome maint~3 commit, but the "-s ours" option tells git to use a special "merge strategy" which, in fact, works by simply keeping the tree you are merging into and ignoring the commit(s) you are merging completely. But it does still make a new merge commit with HEAD and maint~3 as the parents, so the revision graph now says that maint~3 is merged. So in fact you probably want to use the -m option to 'git merge' as well, to explain that that maint~3 commit is actually being ignored!

第二个命令合并了麻烦的 maint~3 提交,但“-s ours”选项告诉 git 使用特殊的“合并策略”,实际上,它的工作原理是简单地保留要合并的树并忽略提交) 你正在完全合并。但它仍然以 HEAD 和 maint~3 作为父项进行新的合并提交,因此修订图现在表示 maint~3 已合并。因此,实际上您可能还想使用 -m 选项来 'git merge',以解释 maint~3 提交实际上被忽略了!

The final command simply merges the rest of maint (maint~2..maint) into master so that you're all synced up again.

最后一个命令只是将 maint (maint~2..maint) 的其余部分合并到 master 中,以便您再次同步。

回答by Alexandre T.

IMHO, the most logical thing to do, is to merge everything, and then use git revert (commit_you_dont_want) to remove it.

恕我直言,最合乎逻辑的做法是合并所有内容,然后使用 git revert (commit_you_dont_want) 将其删除

Example:

例子:

git merge master
git revert 12345678

If you have multiple "to-ignore" commits, or would like to edit revert message:

如果您有多个“忽略”提交,或者想要编辑还原消息:

git merge master
git revert -n 123456
git revert -n abcdef
git commit -m "... Except commits 123456 and abcdef"

Then your history may look like:

那么您的历史记录可能如下所示:

| ... Except 123456 and abcdef
|\ Merge branch 'master' into 'your_branch'

If you have conflicts involving ONLY these "to-ignore" commits, you may use:

如果您的冲突仅涉及这些“忽略”提交,您可以使用:

git merge master -X ours

So your version will persist over the other one. Even without error messages, you may still "revert" those unwanted commits, because they may have other changes that did not conflict, and you still don't want them.

因此,您的版本将持续存在于另一个版本之上。即使没有错误消息,您仍然可以“还原”那些不需要的提交,因为它们可能有其他不冲突的更改,而您仍然不想要它们。

If you have conflicts envolving NOT ONLY the "to-ignore" commits, you should resolve them manually, and you'll probably have to resolve them again during reverting.

如果您的冲突不仅涉及“to-ignore”提交,您应该手动解决它们,并且您可能需要在恢复过程中再次解决它们。

回答by Dustin

Commits include ancestry. You can't merge a commit without merging prior commits.

承诺包括血统。如果不合并先前的提交,则无法合并提交。

You can cherry-pick them, of course. That's a fine flow when you have a branch that's in maintenance mode.

当然,你可以挑选它们。当您的分支处于维护模式时,这是一个很好的流程。

回答by Gilbert

Sounds like a classic case for 'git cherry-pick' https://git-scm.com/docs/git-cherry-pickit does exactly what it sounds like

听起来像是 'git cherry-pick' https://git-scm.com/docs/git-cherry-pick的经典案例, 它确实听起来像

回答by Dmytro

A kind of an advertisement to my projectwhich basically wraps the process described by @araqnid.

我的项目的一种广告,它基本上包装了@araqnid 描述的过程。

It's kind of helper that introduces following GIT flow:

它是一种介绍以下 GIT 流程的助手:

  • there's a daily/weekly notification on pending merges from maintenance branches into dev/master branch
  • branch maintainer checks for the status and decides him/herself whether all commits are required and either block some them or asks developers to block themselves. In the end maintenance branch is merged into the upsteam.
  • 关于从维护分支到开发/主分支的挂起合并的每日/每周通知
  • 分支维护者检查状态并决定他/她自己是否需要所有提交,并阻止某些提交或要求开发人员阻止自己。最后维护分支合并到上游。

A quote from the project page:

来自项目页面的引用:

Depending on the workflow it's possible to have maintenance or customer-specific branches along with the master branch. These branches are also called LTS branches.

Oftentimes the hot fixes go into the branches where the bug was reported and then the commit is merged back into the master branch.

General practice is to have all branches perfectly synchronized with the master, i.e. you want to see a clear delta between a particular branch and master to understand whether the master contains all features and bugfixes.

However sometimes you don't want particular commits because they are customer-specific and shall not be visible by other users. Or your master branch diverged that much that it requires completely different approach to fix the issue, or even better, the problem is not anymore present there.

Also in case of cherry-pick from master into the maintenance branch the resulting commit shall be blocked in master.

根据工作流程,可能有维护或客户特定的分支以及主分支。这些分支也称为 LTS 分支。

通常,热修复进入报告错误的分支,然后提交合并回主分支。

一般的做法是让所有分支与 master 完全同步,即您希望看到特定分支和 master 之间的明确增量,以了解 master 是否包含所有功能和错误修复。

但是,有时您不想要特定的提交,因为它们是特定于客户的,其他用户不可见。或者你的主分支分歧很大,需要完全不同的方法来解决问题,或者更好的是,问题不再存在。

同样,如果从 master 挑选到维护分支,结果提交将在 master 中被阻止。

回答by wilhelmtell

Create a third branch for the changes you want in master10 but not in master20. Always consider master10 as your "master", the most stable branch of all. The branch all other branches want to keep in sync with at all times.

在 master10 但不在 master20 中为您想要的更改创建第三个分支。始终将 master10 视为您的“master”,这是所有分支中最稳定的分支。该分支所有其他分支都希望始终保持同步。

回答by Jason Kleban

Rather than revertor cherry-pickfor this case, you need to get git to consider the changes you're skipping to be older than the ones you made.

而不是revertcherry-pick对于这种情况,您需要让 git 考虑您正在跳过的更改比您所做的更改更旧。

So:

所以:

  1. merge the last commit before the commits you want to skip. This will, of course, merge all commits prior. git merge ccc
  2. merge the commits you want to skip. git merge fff --no-commit
  3. stage any merges, unstage all changes, undo all the changes. (Perhaps there are fool-proof commands for this, but I'd just do this part in a UI - however you know how)
  4. complete the empty merge git merge --continue
  5. merge the commits AFTER the one you wanted to skip. git merge source-branch-head
  1. 在要跳过的提交之前合并最后一个提交。当然,这将合并之前的所有提交。 git merge ccc
  2. 合并要跳过的提交。 git merge fff --no-commit
  3. 暂存任何合并,取消暂存所有更改,撤消所有更改。(也许有针对此的万无一失的命令,但我只是在 UI 中执行此部分 - 但是您知道如何操作)
  4. 完成空合并 git merge --continue
  5. 在您想要跳过的提交之后合并提交。 git merge source-branch-head

After Step 4, git will consider your branch more recent than that commit, since you dealt with it already (by choosing to keep YOUR versions of things).

在第 4 步之后,git 会认为你的分支比那个提交更新,因为你已经处理了它(通过选择保留你的版本)。