Search code examples
gitgit-mergegit-workflow

Merging branch back with clean history


I am working on a branch (with others) off of master.

A - B - C - F - G    (master)
         \
          D - E      (branch-a)

Periodically, we merge master into the branch, to minimize conflicts later.

A - B - C - F - G    (master)
         \       \
          D - E - H  (branch-a)

Eventually, we will want to merge back.

A - B - C - F - G - I - K - M - N  (master)
         \       \       \     /
          D - E - H - J - L - O    (branch-a)

What is the cleanest way I can merge back into master?

  1. I want to preserve the individual commits (i.e. no squash)
  2. I will not use branch-a any longer, so commits hashes can change.
  3. I would like to not include merge commits (e.g. H, L) for merges without conflicts, if possible.

Ideally, it would look like this (assuming there were no conflicts):

A - B - C - F - G - I - K - M - N  (master)
         \                     /
          D  -  E   -   J  -  O

Any ideas on how this should be done?

(FYI, this is a question about my workflow. If I should have done something else earlier, that is a legitimate answer too.)


UPDATE:

After thinking about this some more, I realized this is often not possible.

For example, if J changed a line that G changed, there would not be a way to get that history.

The next best choice would be to have this history:

A - B - C - F - G - I - K - M - D - E - J - O  (master)

Essentially, this is a rebase, but omitting unnecessary merge commits.


Solution

  • You can do this by hand by branching off E and cherry-picking the other commits into the new branch, then merging that into master. Rebasing is also possible, i.e. do

    git rebase C
    

    on branch-a. However, that will take commits from master and put them on your feature branch.

    git rebase -i C
    

    has the same effect, but allows you to skip commits that you are no are from master and are not required on branch-a. Git cannot in general know whether commits interact in any way (e.g. a change to one file might require a change to a different file that was done on master), so there's no fail-safe, fully automatic solution to this problem.