git - 合并时跳过特定提交

发布于 2024-07-16 08:27:18 字数 512 浏览 15 评论 0原文

我已经使用 Git 大约一年了,觉得它太棒了,但我刚刚开始该项目的第二个版本,并为其启动了一个新分支。 我正在为处理未来事情的最佳方式而苦苦挣扎。

我有两个分支,称为 master10 (对于 v1)和 master20 (对于 v2)。 我一直在 master10 分支上的 v1 中进行错误修复,并开发 master20 的新内容。 每当我修复错误时,我都会通过检查 master20 并执行 git merge master10 来将其合并到 v2 中。 到目前为止,一切都很好。

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

我认为 git rebase 可能就是我所需要的,但读完文档后我的头几乎爆炸了。

我认为我想要的是类似于“gitsync”命令的东西,它告诉git两个分支现在是同步的,并且将来只合并从此同步点开始的提交。

任何帮助表示赞赏。

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.

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.

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.

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

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.

Any help appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

守不住的情 2024-07-23 08:27:18

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

因此,让我们假设 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

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

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

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

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...

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:

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

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

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!

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

蓝眼睛不忧郁 2024-07-23 08:27:18

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

示例:

git merge master
git revert 12345678

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

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

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

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

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

git merge master -X ours

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

如果您遇到的冲突不仅涉及“要忽略”的提交,您应该手动解决它们,并且您可能必须在恢复期间再次解决它们。

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

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.

眸中客 2024-07-23 08:27:18

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

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

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.

鸠书 2024-07-23 08:27:18

听起来像是“gitcherry-pick”的经典案例
https://git-scm.com/docs/git-cherry-pick
它的作用正如其听起来的那样

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

海螺姑娘 2024-07-23 08:27:18

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

它是一种引入以下 GIT 流程的帮助程序:

  • 每天/每周有一个关于从维护分支到 dev/master 分支的待处理合并的通知,
  • 分支维护者检查状态并决定是否需要所有提交,然后阻止某些提交或询问开发商自己封锁。 最终维护分支合并到upsteam中。

项目页面的引用:

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

修复程序通常会进入错误所在的分支
报告,然后提交被合并回主分支。

一般做法是让所有分支与
大师,即您希望看到特定之间的清晰增量
分支和主控以了解主控是否包含所有
功能和错误修复。

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

另外,如果从 master 挑选到维护分支
由此产生的提交应在 master 中被阻止。

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

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

  • 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.

云淡风轻 2024-07-23 08:27:18

您可以使用 git-cherry pick 来实现此目的:

git cherry-pick $(git merge-base HEAD origin/branch)..$(git rev-parse <offending-commit-hash>^)
git cherry-pick <offending-commit-hash>..$(git rev-parse origin/branch)

此选择从当前 HEADorigin/branch 的最后一次公共提交中挑选所有提交,直到提交被忽略(注意>^ 告诉cherry-pick 在该提交的父级停止)。

第二个命令从 中挑选所有内容以及 origin/branch 的其余部分。

请注意,如果需要跳过提交来合并其他补丁,则可能仍然需要一些修补(git 将停止cherry-pick 并告诉您解决冲突)。

You can use git-cherry pick for this:

git cherry-pick $(git merge-base HEAD origin/branch)..$(git rev-parse <offending-commit-hash>^)
git cherry-pick <offending-commit-hash>..$(git rev-parse origin/branch)

This cherry-picks all commits from last common commit of current HEAD and origin/branch until commit to be ignored (note ^ telling cherry-pick to stop at parent of that commit).

Second command cherry-picks everything from <offending-commit-hash> with rest of origin/branch.

Note that some tinkering might be still needed if skipped over commit is needed to merge other patches (git will stop cherry-pick and tell you to resolve conflicts).

始终不够爱げ你 2024-07-23 08:27:18

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

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.

滿滿的愛 2024-07-23 08:27:18

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

因此:

  1. 合并您要跳过的提交之前的最后一次提交。 当然,这将合并之前的所有提交。 git merge ccc
  2. 合并您想要跳过的提交。 git merge fff --no-commit
  3. 暂存任何合并、取消暂存所有更改、撤消所有更改。 (也许有一些万无一失的命令,但我只是在 UI 中执行这部分 - 但你知道如何)
  4. 完成空合并 git merge --continue
  5. 合并提交之后的提交你想跳过。 git merge source-branch-head

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

Rather than revert or cherry-pick for this case, you need to get git to consider the changes you're skipping to be older than the ones you made.

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

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文