简体   繁体   English

Git工作流程是否可以进行部分合并?

[英]Git workflow for partial merges?

I have a two branches dev and a . 我有两个分支机构deva I need to merge feature a into dev , but my teammate has made certain features in one file that is not ready for merge. 我需要将功能a合并到dev ,但是我的队友已经在一个尚未准备好合并的文件中创建了某些功能。 If I just merge and resolve using mine, git marks the changes in this file as invalid, and rather than permitting these changes to merge at a later time, just fast forwards if I try to re-merge the branch. 如果我只是使用我的合并和解析,则git将此文件中的更改标记为无效,而不是允许这些更改在以后合并,如果我尝试重新合并分支,请快速前进。 If I don't resolve conflicts, git refuses to perform the merge. 如果我不解决冲突,则git拒绝执行合并。

My strategy for working around this is to create a branch aside and suppress the broken feature, then merge in this branch. 解决此问题的策略是在旁边创建一个分支并抑制损坏的功能,然后在该分支中合并。 The problem is that the git commands for this get somewhat complicated, so I need the help of an expert. 问题是为此的git命令变得有些复杂,因此我需要专家的帮助。

I would like if possible to generalize this type of action, into a git extension I would call something to the effect of git-cherrymerge . 我想尽可能将这种类型的动作推广到git扩展中,我称之为git-cherrymerge

The steps would be as follows: 步骤如下:

  1. Replay commits specified by user (maybe this can be automated with some strategy) onto a temporary branch 将用户指定的提交(也许可以通过某些策略自动执行)重播到临时分支上
  2. Git filter-branch to remove the broken files git filter-branch删除损坏的文件
  3. Squash temporary branch, adding automatic commit message 压榨临时分支,添加自动提交消息
  4. Merge temporary branch into target branch (here it's dev) 将临时分支合并到目标分支(此处为dev)

I'm not quite an expert in filter-branch or rebase and it looks like I can quite seriously damage the history by misusing them . 我不是很专家filter-branchrebase ,它看起来像我可以很认真地滥用武器伤害的历史

I suppose my question is 我想我的问题是

  1. Will this work or is there a better canonical way to do this? 请问这项工作还是有更好的规范方法来做到这一点?
  2. What git commands should I execute in what sequence to avoid accidentally damaging my repositories history. 我应该按什么顺序执行什么git命令,以免意外损坏存储库历史记录。

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. R1和R2正在重构更改。 B1 and B2 are bugfix changes. B1和B2是错误修正更改。 F1 and F2 are incomplete features. F1和F2是不完整的功能。 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 . 使用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. Git将通过以新顺序应用这些补丁来重建分支。 You might have to resolve conflicts. 您可能必须解决冲突。 For more info, see Rewriting History in Pro Git . 有关更多信息,请参见在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. 仅仅是git branch fixes beadbee从声明的最后一次提交开始声明fixes分支。

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 . 像以前一样使用git rebase -i ,但是将要拆分的提交设置为edit而不是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. 然后,Git将停止该提交,并允许您按自己的喜好对其进行编辑。 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. 使用git add -p仅将部分更改添加到登台区域(在其中构建提交),而git commitgit commit部分更改。 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 . 您可以在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 push ,否则不会影响任何其他人。 Git doesn't rewrite history, it writes new history and pretends it was that way all along. Git不会重写历史记录,而是会编写新的历史记录并假装一直都是这样。 The old history is still there, for a while, and you can go back to it using things like ORIG_HEAD and git reflog . 过去的历史仍然存在了一段时间,您可以使用ORIG_HEADgit reflog类的东西来追溯到过去。

Worst case scenario, delete your local repository and clone a new one . 最坏的情况是, 删除本地存储库并克隆一个新的存储库

I've marked Schwern's answer as the correct one, since it's the most general case - but it's worth noting that for my case there was a very simple strategy as follows. 由于这是最普遍的情况,因此我将Schwern的答案标记为正确的答案 -但值得注意的是,对于我的情况,有一个非常简单的策略如下。 Since I intended to squash the changes anyway, that means that the procedure can be done in a single commit. 由于我打算压缩所有更改,因此这意味着该过程可以在一次提交中完成。 It is still necessary to create a new branch, but it can be done quickly using a soft reset. 仍然有必要创建一个新分支,但是可以使用软复位快速完成。 If there are only a small easily manageable number of changes that you want to defer I would recommend this strategy 如果您要推迟的更改数量很少且易于管理,那么我建议您采用这种策略

  1. Checkout the HEAD of A 检出A
  2. Branch to a temporary branch 分支到临时分支
  3. Git soft reset to the "root" of A 将Git软重置为A的“根”
  4. Commit changes excluding the ones you don't want 提交更改(不包括不需要的更改)
  5. Merge Into develop 合并develop

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM