84

I forked a repository on Github. I've made some minor changes and submitted pull requests to the upstream, but along the way my fork has become so mangled I'm unable to generate clean pull requests; when I start a pull request from a branch with six changes, Github wants to submit thirteen, with seven of them already existing upstream (natch).

My problem seems to be related to only pulling the latest commits, but when I create a new branch and cherry-pick commits I still have extras. I've futzed with rebasing as well, but now it looks like even my master is so messed up I can't generate a clean copy of upstream. This is apparently because I didn't understand that I needed to rebase instead of merging, so clearly I've made mistakes; what I'm trying to do is figure out how to unsnarl that knot and get back to a clean state where I can move forward usefully.

I kind of want to blow away my fork and make a new fork of the upstream, but I gather that, too, is difficult.

Having confessed my Git sins, how do I obtain github absolution?

Community
  • 1
  • 1
pjmorse
  • 9,204
  • 9
  • 54
  • 124

3 Answers3

104

Step 1: Pull upstream changes
It's recommended to add the upstream repo as "upstream" as explained on the Fork a Repo page:

git pull --rebase upstream master

The --rebase option places your changes on top of the latest commit without merges.

Step 2: (Optional) Merge your commits into 1 commit

git reset --soft upstream/master

This command will "undo" all your commits, but won't change the files. So you can commit all your changes in a single commit.

git commit -a

Step 3: Check & test your changes

To show the changes use a GUI like the built-in gitk, Sourcetree, TortoiseGit or Tower (paid), etc.

Step 4: Push

git push will throw an error, because the push would change the target repository's history.
If you're confident the changes shown in step 3 are correct then push with "-f"

git push -f origin master


Additional information
The command to add a remote is:

git remote add upstream git://github.com/[username]/[project].git

You can also also pull from a direct URL:

git pull --rebase  git://github.com/[username]/[project].git

But then you'll need the hash of the latest upstream commit instead of "upstream/master" in the other steps.

Bob Fanger
  • 28,949
  • 7
  • 62
  • 78
  • 3
    Thank you very much. GitHub should update their [Fork A Repo](http://help.github.com/fork-a-repo/). – buschtoens Dec 02 '12 at 13:48
  • Thanks! I had tried numerous ways to solve this problem, nothing worked. Was about ready to blow away my fork before finding this answer...and it worked. Thanks! – Judah Gabriel Himango Mar 04 '14 at 20:37
  • Hi, @JudahHimango. Have you followed the "step 2" too. Because I'm in the same situation like you. Can you help me. – arunit21 Aug 20 '14 at 06:13
  • This is a great resource. Thanks! – Dr. Jan-Philip Gehrcke Jul 29 '15 at 11:09
  • My forked repo kept saying it was out of sync with the upstream, so I would pull down and merge - which lead to commits on my fork that weren't necessary. Using this approach and forcing the push has sorted this. I also used rebase to combine some of my earlier commits: git rebase -i HEAD~n [where n is the number of commits] – The Coder Jun 15 '17 at 04:39
4

As I understand it, with both Git and Mercurial (I've only used the latter, so I may be wrong) it isn't a big deal at all to blow away a fork and re-fork it. I do that all the time with my projects. If you're ok with doing that (can back up your changes, or don't have any significant changes in your fork), I'd say that's probably the way to go.

Remember, with DVCS, forking a repository makes a full clone of that entire repo. If you delete your current fork and then fork the original repo again, you'll have a completely clean slate to work from.

Sean Edwards
  • 2,062
  • 1
  • 18
  • 19
  • Fork in this case is a special feature of github, not core git, though it uses core git features. There are special github administrative abilities you can do with github-forks. – Seth Robertson May 23 '11 at 20:11
  • 1
    Ah, I see. I use BitBucket primarily, and on there "Fork" is synonymous with "clone" when you're working with personal working copies. I'll leave my answer here anyway though just in case. – Sean Edwards May 23 '11 at 20:20
  • Yeah, I've deleted my local clone and re-cloned several times already. I did an experiment with another repo and it looks like there isn't a problem with deleting a fork and creating a new one from the same source. – pjmorse May 23 '11 at 20:55
  • N.B. I'm using `git format-patch` to preserve the commits I want to save first. – pjmorse May 23 '11 at 20:55
  • 1
    Deleting your forked repository and reforking is unnecessary, and using `git format-patch` to save your work is sort of side-stepping all the helpful tools that git has for managing branches. In the future, using `git rebase -i` to selectively rewrite your commits on the top of the new upstream `master` branch is the right thing to do. – Mark Longair May 24 '11 at 04:58
0

On your private repo, add the forkee's repo as a remote. Rebase/reset your branches from the remote's branches. Do a force push to your github repo.

If you need exact commands, let me know. Also let me know whether you want to try and preserve local commits or if "blowing away" is OK.

Seth Robertson
  • 30,608
  • 7
  • 64
  • 57