用于部分合并的Git工作流程?

时间:2017-04-09 22:33:33

标签: git version-control merge git-filter-branch cherry-pick

我有两个分支deva。我需要将功能a合并到dev,但我的队友已在一个文件中创建了某些尚未准备好合并的功能。如果我只是使用我的合并和解析,git会将此文件中的更改标记为无效,而不是允许这些更改在以后合并,如果我尝试重新合并分支,则只需快进。如果我没有解决冲突,git拒绝执行合并。

我解决这个问题的策略是创建一个分支并抑制破坏的特征,然后合并到这个分支中。问题是这个git命令有点复杂,所以我需要专家的帮助。

如果可能的话,我希望将这种类型的操作概括为一个git扩展,我会称之为git-cherrymerge的效果。

步骤如下:

  1. 用户指定的重播提交(可能会通过某种策略自动执行)到临时分支
  2. Git filter-branch删除损坏的文件
  3. 壁球临时分支,添加自动提交消息
  4. 将临时分支合并到目标分支(此处为开发者)
  5. 我不是filter-branchrebase的专家,看起来我非常认真地通过滥用来破坏历史

    我想我的问题是

    1. 这样做还是有更好的规范方法来做到这一点?
    2. 我应该以什么顺序执行哪些git命令,以避免意外损坏我的存储库历史记录。

2 个答案:

答案 0 :(得分:4)

You've basically got the right idea, you want to turn one branch into two: a branch with the stuff that's ready to go, and a branch on top of that which is the incomplete changes. For example, a branch might contain a bunch of refactoring and bug fixes interleaved with incomplete features.

A - B - C - D [master]
         \
          R1 - B1 - F1 - R2 - B2 - F2 [feature]

R1 and R2 are refactoring changes. B1 and B2 are bugfix changes. F1 and F2 are incomplete features. What you want is this:

A - B - C - D [master]
         \
          R1 - B1 - R2 - B2 [fixes]
                           \
                            F1 - F2 [feature]

There's two steps there, reordering the commits and declaring the new branch. Reorder the commits with git rebase -i. This will present something like:

pick f37beee Refactor 1
pick 7f238ea Bugfix 1
pick d100dd2 Feature 1
pick aa1124b Refactor 2
pick beadbee Bugfix 2
pick 0123abc Feature 2

Then you literally reorder them in the editor.

pick f37beee Refactor 1
pick 7f238ea Bugfix 1
pick aa1124b Refactor 2
pick beadbee Bugfix 2
pick d100dd2 Feature 1
pick 0123abc Feature 2

Git will rebuild the branch by applying those patches in the new order. You might have to resolve conflicts. For more info, see Rewriting History in Pro Git.

Then you need to declare a new branch. That's just git branch fixes beadbee to declare the fixes branch starting at the last commit you want.

Merge fixes into master normally, and rebase feature on top of master.


But often the commits are not so neatly split out. If you had a commit which contains multiple changes and you only want some of them, you can turn it into multiple commits.

Use git rebase -i as before, but set the commit you want to split up as edit instead of pick.

pick f37beee Refactor 1
pick 7f238ea Bugfix 1
pick aa1124b Refactor 2
pick beadbee Bugfix 2
edit beacd4a Messy commit
pick d100dd2 Feature 1
pick 0123abc Feature 2

Then Git will stop on that commit and allow you to edit it how you like. Use git add -p to add only pieces of the change to the staging area (where you build a commit) and git commit only the partial changes. Do this until each change has its own commit. For example, maybe it changes the name of a method, fixes a bug, but also changes an unrelated method. You'd split those into three commits: one to change the name, one to fix the bug, and one to change the unrelated method.

You can read more about that in Interactive Staging.


I'm not quite an expert in filter-branch or rebase and it looks like I can quite seriously damage the history be misusing them.

Yes, but you can reverse those mistakes, and nothing will affect anyone else unless you git push it. Git doesn't rewrite history, it writes new history and pretends it was that way all along. The old history is still there, for a while, and you can go back to it using things like ORIG_HEAD and git reflog.

Worst case scenario, delete your local repository and clone a new one.

答案 1 :(得分:0)

我已将 Schwern的答案标记为正确答案,因为它是最常见的案例 - 但值得注意的是,就我的情况而言有一个非常简单的策略如下。因为无论如何我打算压缩更改,这意味着该过程可以在一次提交中完成。仍然需要创建一个新分支,但可以使用软重置快速完成。如果您只想推迟易于管理的小数量的更改,我会推荐此策略

  1. 查看A
  2. 的HEAD
  3. 分支到临时分支
  4. Git soft reset to" root" A
  5. 提交更改,不包括您不想要的内容
  6. 合并到develop