7

My company's policy is that any pull request must be done with a rebased branch. I have a local Dev branch and this has 'task' branches:

remote master --------
     \   
     Dev ------------------
            \-----task1  \
                          \---task2

When master gets updated, I rebase Dev on master. What is a optimal way to manage branches task1 and task2. They are still being worked on. Rebasing each task branch seems like the only way I can see.

Josef.B
  • 942
  • 8
  • 16
  • Yeah, it is. Unless you cherry-pick instead of merge, but that doesn't work very well with pull requests. – scrowler Apr 30 '17 at 22:58

2 Answers2

7

Try first do rebase dev while preserving merges:

git checkout Dev
git rebase --preserve-merges master

That should keep task1 and 2 correctly rebased as well.

See "What exactly does git's “rebase --preserve-merges” do (and why?)"

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • This is because I've been merging in the taskN branches into Dev periodically, so as long as the Dev is rebased with --preserve-merges, the taskN merges are still recorded. Sort of like applying @Bert F method? – Josef.B May 02 '17 at 10:33
  • @Josef.B no need: just rebase -p master should be enough. I hadn't seen Bert's answer (at the time, I was the only answer) – VonC May 02 '17 at 10:35
  • We must be reading the graphic differently - left to right vs right to left. I see task1 and task2 as the tips of 2 branches branched off of a commit of Dev, which is branched off of remote master, i.e. 3 divergent heads - Dev, task1, task2 - not yet merged together. I guess you are seeing task1 and task2 branches as already merged into Dev, i.e. 1 head with the other 2 branches in its history. If it's the latter, then I agree that --preserve-merges is enough. If it's the former, then simply rebasing Dev by itself won't be enough. – Bert F May 20 '17 at 18:24
  • @BertF Yes, re-reading the question, I believe your interpretation is the right one. So +1 – VonC May 20 '17 at 19:38
  • You're a class act @VonC. – Bert F May 21 '17 at 20:59
5

If you have a lot of task branches, then the best I can think of is to temporarily octopus merge them with Dev into a temp branch and then rebase temp onto master with --preserve-merges. Then reset the branch labels to the proper places.

$ git checkout -b temp Dev && git merge task1 task2
$ git rebase master --preserve-merges
$ git checkout Dev   && git reset --hard temp^
$ git checkout task1 && git reset --hard temp^2
$ git checkout task2 && git reset --hard temp^3
$ git branch -D temp

It's still a lot of commands, but:

  1. Since the tree is inherently preserved, it saves you from having to manually reconstruct the graph, i.e. less human error from having to graft each task branch onto the proper corresponding commit of the rebased Dev branch. It's just a matter of resetting the Dev and task branch markers onto the correct parent commit, which corresponds to the order they were used/named in the octopus merge.

  2. If you have to do this kind of thing a lot, this should be straightforward to script and use as an alias.

Bert F
  • 85,407
  • 12
  • 106
  • 123
  • 1
    Would I be correct in stating that you want the merge to use --no-ff if there are only two branches involved? I did this and didn't have a HEAD^2, and what I would have expected to be HEAD^2 was HEAD, likely because the merge did a ff. – RoboCop87 Dec 06 '17 at 20:03
  • 1
    @RoboCop87 - agreed - the merge will fast-forward when possible (which is likely if there was 2 branches, i.e. Dev and task1), so using --no-ff would be necessary to ensure the desired merge behavior. – Bert F Dec 08 '17 at 12:24