Github rebase upstream/master with origin/master
Asked Answered
A

2

11

I'm rather new to github social coding and are having trouble following github guidelines. I'll try to describe what happened and what I'm trying to achieve - hoping that more experienced git wizards can help me figure out the arcade commands needed to get there.

What happened

  1. I forked MassTransit back in July 2012. Its master branch back then was at version v2.1.1, with last commit on Mar 29, 2012.
  2. Following github advice, I then started coding some changes on a topic branch.
  3. A few commits later, when the feature was finished, I merged my topic branch into my clone's local master and then pushed that to github.
  4. Ever since Mar 29, 2012, MassTransit was being developed on its develop branch. All of those changes, making up v2.6.0, were merged with its master recently.

What I'd like to do

I'd like to get all changes that were merged into upstream/master. Preferrably as their respective commits, not one massive commit of hundreds of files. Because I was doing development on the former upstream/master (dated Mar 29, 2012), I guess would effectively need to "insert" some commits in between the last upstream/master change of Mar 29 and my first commit of Aug 8, and then on top of that add those that happened later. How do I do that?

(I'd also like not to destroy my commits/fork in the process ;-)

What I tried

git checkout master
git remote add upstream git://github.com/phatboyg/MassTransit.git
git rebase upstream/master
git push

However, it would not let me then do git push, complaining that my local tip was 10 commits behind the origin (possibly the commits I made on my topic branch and later merged into origin/master?).

Recommendations?

It seems that I may have been bitten by recommendations. Eg. perhaps it would be better to create a separate branch, eg. local-master, and treat that as... well, my own master. Then master would be there only for keeping in touch with upstream/master, and I would occasionally rebase origin/master with upstream/master and merge with origin/local-master...

How do you guys manage your forks?

Other questions

I've been unable to find a way to visualize branch history, what branch was merged with another and when, etc. Github for Windows only shows a flat history for the currently selected branch (sad face here). The website does have some visualizations for the network (here is one for MassTransit), but this feels a lot less informative than say the graphs in TortoiseHg. Am I missing something obvious? Does everyone else just remember what was merged with what and when?

Edit (31st August)

I'm sharing a poor-man's visualization to help explain what happened.

  1. I forked when C1 was latest on upstream/master.
  2. I then developed on my origin/feature-1.
  3. One the feature was complete, I merged it with my origin/master.
  4. When upstream/mega-feature was completed, it was merged with upstream/master, effectively historically copying C2 and C3 to upstream/master. (Or perhaps upstream/master was rebased with upstream/mega-feature?)
  5. I would now like to copy C2, C3 and C4 to my origin/master.
Aliber answered 30/8, 2012 at 14:54 Comment(3)
use merge instead of rebase. Why are you using rebase?Zolazoldi
I thougt that using merge would only apply all 'upstream/master' changes to my repo and leave it in an uncommited state. And so while producing correct results in terms of the state of my source files, upon committing I would get one huge commit changing about 600 files, without more granular information. AFAIK rebase would prevent that, and would instead pull individual commits. Correct?Aliber
I've updated my question to help explain what happened and what I'd like to do.Aliber
C
6

I assume that you will be, or have, set up an origin remote to your fork, and the same again for upstream (as described).

I would then do a fetch of the upstream so that you have all their branches held locally. You can then make the comparisons between the repos and see if there is a common commit at or near the divergence date.

The gitk --all visualisation is useful here. Don't forget that even if you do a rebase the old commit series is still there so you can give it a name


[EDIT] A wordy description.

Clearly the merge commit is 'getting in the way' so needs to be massaged away so that the repos can be brought in sync again.

  1. create a temp branch at your current head, so nothing gets lost.
  2. reset your master branch back to the last common commit between you and upstream.
  3. reset your feature branch to just before the merge.
  4. checkout that merge commit to get the working tree as you expect, then
  5. switch to your feature branch (without checking out anything!)
  6. commit that fixed work tree on your feature branch (i.e. no merge).

You now have a clean line on master, a clean but old line on feature, and any post merge developments on temp. if Happy, you should be able to force push this to your origin.

  1. pull from upstream - it (i.e. master, etc.) should all fast forward.
  2. rebase those post merge developments from temp onto feature (if required).
  3. rebase feature to the last commit you know well on master (should be relatively easy).
  4. rebase feature (again) to the latest commit on master, fixing up as you go (combine with the last step if it's easy;-).

This should finally give you a clean line of feature development at the head of master, and suitable for pulling upstream without any conflict.

Connected answered 30/8, 2012 at 22:43 Comment(6)
Yes, origin was set up for me when I cloned my repo in Github for Windows, I only needed to add upstream (confirmed by doing git remote, which shows both origin and upstream). What do you mean by common commit? I know the precise commit after which my repo diverged. What can I do with that information?Aliber
It was a case of mapping where the three different branches diverged from each other to see if there was some conflicts (overlaps) or whether you had independent lines of development (excepting for the merge commits). Is your topic branch still one behind the merge to your master?Connected
I've updated my question to help explain what happened and what I'd like to do, please have a look.Aliber
Sorry for the delay. I've updated my answer with an extended description of what could be a method for doing the fixes.Connected
Just now I tried something very similar to what you suggest. First of all I did a git reset HEAD~10, reverting the feature-with-head merge, then git push --force. With that force I felt some previously unknown powers :-) So I rebased my feature branch, fixing errors along the way, and again did a git push --force of my feature branch. This was key, as merge conflicts when doing an ordinary git push led to errors, fixing whom reverted me back to pre-rebase state. Thank you for your ideas, they did help me along my rocky path to better git understanding.Aliber
@Dav, no problem. I know the feeling;-) It's also good to get you feedback on what you did in practice to help others. Let's hope your suggestions get picked up by your upstream.Connected
A
2

Here are some ideas.

Cherry pick method:

git checkout master
git cherry-pick C2..C4

New branch rebase method:

git checkout upstream/master
git branch new-master
git rebase master
# new-master should now look like what you want, once you confirm this
git branch -m master old-master
git branch -m new-master master

Rebase --onto method (lets you pick which range of commits you want):

git checkout master
git rebase --onto master C2 C4 # puts you into a detached HEAD
git branch new-master
# rename branch as above if it is correct
Antofagasta answered 31/8, 2012 at 10:29 Comment(1)
Nice one mentioning cherry picking, will try that in the future!Aliber

© 2022 - 2024 — McMap. All rights reserved.