5

I'm in a bit of a pickle.

I started development on a fork of a repo a few months ago. I made some changes. I was about to push my code back to the master as a pull request, but I realized there were quite a few changes in the meantime...

So, following the instructions at Github under "Pull in Upstream Changes" I tried:

$ git remote add upstream ...  # savon/httpi
$ git fetch upstream
$ git merge upstream/master
$ git push origin/master       # coldnebo/httpi

However, now my fork is rather messy. I'm still rather a novice with git, so instead of trying to guess what the terminology is I'll simply show you what I got and what I expected:

This is the diff I want. Is there any way to rebase/revert and do this without losing my changes?

what a mess.

maybe git pull would have been better?

It's not many changes, so if it's unrecoverable I can always manually diff and remaster it, but I'm looking for the "right way" to do this in the future.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
Larry Kyrala
  • 889
  • 2
  • 8
  • 18

3 Answers3

6

You should always create new branch for each Pull Request your create. Before you going to push it to github to create the request, you should rebase your branch to the latest upstream branch.

Github says you use git merge for this, I prefer to use git rebase upstream/master if there aren't much changes, this will prevent merge commits.


Sometimes the rebasing can't continue, because something what you have changed was already changed in the upstream branch. For instance, assume that you have a text.txtfile like:

Lorem ipsum

You create a PR to update this to Lorem ipsum! and the upstream branch already changed this to Hello World If you do a rebase, to make your code up to date before creating a request, you get a merge conflict. The file is updated with conflict markers and you can choose which version you want to use and you can even edit it, in our example we get this in text.txt:

<<<<<<< YOUR_PR_BRANCH
Lorem Ipsum
=======
Hello World
>>>>>>> THE_UPSTREAM_BRANCH

After this, add the updated files with git add and execute git rebase --continue.

Wouter J
  • 41,455
  • 15
  • 107
  • 112
  • Why would you want to prevent merge commits? You make it sound like they are wrong or evil or something? – CB Bailey Jan 07 '13 at 16:21
  • @CharlesBailey Merge commits aren't evil, but they are the most useless and most vague commits in your workflow. One other feature of rebase is that it remains the history, it will not put all new commits before/after your commits, it will put those where they needed to be. – Wouter J Jan 07 '13 at 16:29
  • 3
    I think you may have misunderstood merge commits and history. Merge commits correctly record when you merged two (or more) parallel workflows together. Rebase disguises true history because it combines the original change with a merge and pretends you made the original change at a different point in history to when you actually did. Rebase does anything but retain history. I'm not sure what makes you say that merge commits are vague or useless; they accurately record exactly what was done in a merge, definitely not vague and potentially very useful. – CB Bailey Jan 07 '13 at 16:35
  • 1
    I really like this discussion, it touches on some of the confusion I was getting from the docs. So my primary goal in submitting a pull request is to allow the upstream maintainer to review ONLY my changes, since they already know about their changes. My question is whether this is a git process problem (ie use rebase) or a diff review problem (use merge commits, but some other technique for separating the new commits from the rest on review)? I'd prefer to do things right by git first and then consider artifacts of the github process, but any perspective is welcome. – Larry Kyrala Jan 08 '13 at 09:57
6

Ok, if your repo is fubar, then here's steps to recover:

$ git remote update     # make sure origin and upstream are up to date
$ git checkout master
$ git branch my_changes   # just to make sure my stuff isn't lost
$ git reset --hard upstream/master
$ git status
# On branch master
# Your branch is behind 'origin/master' by 8 commits, and can be fast-forwarded.
#

Ignore that fast-forward crap, it won't help you, just reset the master.

$ git push origin +master   # now, fork matches upstream/master

Now, how to recover the previous work so it's reviewable?

$ git diff --no-ext-diff --no-prefix master..my_changes > patchfile
$ patch -p0 < patchfile   # apply the patchfile to master
$ git diff     # to verify patch visually.
$ rm patchfile   # clean up
$ rake spec      # verify that it really works.
$ git add .
$ git status     # double triple verify
$ git commit .
$ git push origin master

That sucked. I tried doing rebase, but it kept saying "no changes" and didn't ask me to check anything in? I'm pretty sure I don't understand what's going on here, which is why I posted my struggle so someone can explain how I could have avoided this mess and gotten from A to B more elegantly now that it's fully documented. I'm willing to chalk this up to git inexperience, but I figure that pulling changes should be a really common thing in git -- I must be missing something.

Larry Kyrala
  • 889
  • 2
  • 8
  • 18
2

git pull --rebase works for me and keeps the history clean.


if working with multiple remotes and branches it may be beneficial to specify a remote and a brach, ie.

git pull --rebase [REMOTE] [BRANCH]
git pull --rebase upstream master

the upstream is defined as a remote for a git repo that can be printed with git remote -v

ipatch
  • 3,933
  • 8
  • 60
  • 99
aragaer
  • 17,238
  • 6
  • 47
  • 49