Merge dev to stage but only specific commits

32 Views Asked by At

I want to merge my dev branch into stage but there are some commits that should not go to stage. One solution is to use cherry-pick but there are just too many commits to cherry-pick so it is not feasible. Is there any solution to take my changes from dev to stage without merging dev completely into stage.

I tried to use cherry pick but the first one I did, it had conflicts. There is no way I am doing this with 300 commits.

1

There are 1 best solutions below

0
eftshift0 On

Suppose you have this:

* fff (dev) fffffffff
* eee eeeeeeeee
* ddd ddddddddd
* ccc ccccccccc
| * bbb (stage) bbbbbbbbb
| * aaa aaaaaaaaa
|/
* zzz some common ancestor

Suppose you want to merge dev into stage but you do not want to include the changes from eee and ddd.

You could create a temporary branch and revert the commits from there:

git checkout -b temp dev
git revert eee
git revert ddd

Now you have this:

* hhh (temp) reversal of ddd
* ggg reversal of eee
* fff (dev) fffffffff
* eee eeeeeeeee
* ddd ddddddddd
* ccc ccccccccc
| * bbb (stage) bbbbbbbbb
| * aaa aaaaaaaaa
|/
* zzz some common ancestor

Now, we proceed to merge into stage:

git checkout stage
git merge temp

And we get this:

* iii (stage) merge of temp
|\
* | hhh (temp) reversal of ddd
* | ggg reversal of eee
* | fff (dev) fffffffff
* | eee eeeeeeeee
* | ddd ddddddddd
* | ccc ccccccccc
| * bbb bbbbbbbbb
| * aaa aaaaaaaaa
|/
* zzz some common ancestor

Now, time has gone by and dev has more commits:

* kkk (dev) yet more work in dev
* jjj more work in dev
| * iii (stage) merge of temp
| |\
| * | hhh (temp) reversal of ddd
| * | ggg reversal of eee
|/ /
* | fff fffffffff
* | eee eeeeeeeee
* | ddd ddddddddd
* | ccc ccccccccc
| * bbb bbbbbbbbb
| * aaa aaaaaaaaa
|/
* zzz some common ancestor

Say that at this point, you consider that you want to merge dev again into stage and now that you are merging the full branch, you would expect to see the changes from ddd and eee show up in the branch, right? Well.... not really... that can't happen because those commits are already merged into stage. You can see that the commits are already in the history of stage... another to look at it is by looking at the last common ancestor between stage and dev... where is it? It's fff and only commits past this commit will be considered on the merge... ddd and eee are not past fff and so you are out of luck..... you won't see those changes show up.... unless you come up with a magic trick.... you can undo the reversal that you did in temp and merge it back into dev... something like[1]:

git checkout temp
git revert hhh # reapply changes from ddd
git revert ggg # reapply changes from eee
git checkout dev
git merge -m "Undoing the reversal of ddd and eee" temp

And now you have a chart like this:

* nnn (dev) Undoing the reversal of ddd and eee
|\
|  \
|   * mmm (temp) Reversal of ggg # just like reapplying eee
|   * lll Reversal of hhh # just like reapplying ddd
*   | kkk yet more work in dev
*   | jjj more work in dev
| * | iii (stage) merge of temp
| |\|
| * | hhh reversal of ddd
| * | ggg reversal of eee
|/ /
* | fff fffffffff
* | eee eeeeeeeee
* | ddd ddddddddd
* | ccc ccccccccc
| * bbb bbbbbbbbb
| * aaa aaaaaaaaa
|/
* zzz some common ancestor

And now, starting from the same common ancestor between dev and stage, we have the changes from ddd and eee reapplied so when you merge, the changes will show up.

[1] The reversal of all those commits could have been done with just a single command, instead of having multiple git revert:

git checkout temp
git restore --worktree --index --source fff -- . # the commit before the first revert we did
git commit -m "Reapplying all commits we reverted... in a single shot"