Question

My commit-tree described below:

--(+A)--(+B)-+-(-B)--(+E)--(master: AE)
              \
               +--(+C)--(+D)--(branch: ABCD)

Some changes have been reverted in master. We need to merge the changes from the branch to master reverting reverted commit.

Does one-step way exists? Or only one way is cherry-pick (B) to master before merging the branch?

P.S. Final master must look like: (ABCDE) - order is not important

Was it helpful?

Solution

If you absolutely must have A-B-C-D-E as the order of your commits then you will need to cherry-pick C and D. This will end up with (A) - (+B) - (-B) - (E) - (C) - (D). Then you can git rebase, you can remove (-B) and reorder C and D to be before E.

If you do that, then you don't want to merge your branch. git cherry-pick creates a new commit that has the same changes. So when you merge it can cause some problems.

http://git-scm.com/book/en/Git-Branching-Rebasing#The-Perils-of-Rebasing

If you are dealing with a remote branch, and all of these commits are pushed. You should not do this. You are changing history on a remote and this can cause issues with other people getting the changes. Just merge the branch into master, resolve any conflicts correctly and you will end up with the code in the state that you are looking for. Having a nice linear git history is nice but it is not always necessary to have. Having a revert commit in the log is not a bad thing.

OTHER TIPS

I faced a close problem, but I must neither remove commits from nor reorder them in master. And I needed to rebase branch ABCD in order to get a proper commit history. Also I wanted to avoid applying B again. That's how I worked this situation around.

--(+A)--(+B)--(-B)-+-(+E)--(master: AE)
            |\
            | +-(+C)--(+D)--(branch: ABCD)
            |
             \+ cherrypick (-B) + revert(-B) + merge ABCD (+C') -(+D') + rebase AE (+E)  -- (branch: AB-BE--BC'D')

Obtained branch AB-B--BEC'D' can be easily merged to master or used to further development.

I would do it this way:

git checkout branch
git merge $minusB^    # only if -B is not right after the fork point
git merge -s ours $minusB
git merge master

That is, merge everything up to right before the reversal of B, then merge the reversal of B, but ignore the changes that it introduces, and finally merge the rest of master.

A few ideas:

  • you can rebase master and skip -B
  • you can drop the whole master and set master HEAD to D and cherrypick E.
  • but maybe the easiest one is what you mention to cherry-pick B again to master.

According to the provided answers there is no one-step way to reach the goal. I think the better way to deal with situations described above is following branching scenario:

--(+A)--(+B)--(-B)-+-(+E)--(master: AE)
                    \
                     +--(+B)--(+C)--(+D)--(branch: ABCD)
--(+A)--(+B)-+-(-B)--(+E)--(master: AE)
              \
               +--(+C)--(+D)--(branch: ABCD)

if your net tree is above, and you want ABCDE after merging. You can create a new branch like "revert -B" at (-B), then do git revert HEAD, thus you will have all things same with (+B), at this time, you can safely merge branch "ABCD" to current branch without any conflicts. Finally checkout to master and merge your branch "revert -B", done.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top