168

I have completely fubar'd my local branch, and would like to start over. The version on the server is correct.

I don't want to start over, I would like to use my local history to fix my huge screwup. (I can if I have to.)

git fetch branchname, and git pull branchname don't work. The message I get is "up to date" however, my local version does not match that of the server.

git pull origin/branchname gives me a "not found" error.

Jeroen
  • 60,696
  • 40
  • 206
  • 339
Sara Chipps
  • 9,322
  • 11
  • 58
  • 103

4 Answers4

276

first, create a new branch in the current position (in case you need your old 'screwed up' history):

git branch fubar-pin

update your list of remote branches and sync new commits:

git fetch --all

then, reset your branch to the point where origin/branch points to:

git reset --hard origin/branch

be careful, this will remove any changes from your working tree!

cregox
  • 17,674
  • 15
  • 85
  • 116
knittl
  • 246,190
  • 53
  • 318
  • 364
  • 2
    +1 but you might want to add a reminder to do `git fetch origin` before the reset – Mark Longair Jun 03 '11 at 16:22
  • I did this with one slight change and it didn't work: git fetch --all, git reset --hard SHA1OFANOLDCOMMIT, (some other stuff), git reset --hard origin/branch. The end result was that I was still at the old commit. So, this approach may work in some cases, but I think it doesn't work in all. – greggles Oct 18 '12 at 15:56
  • @greggles: Any errors? After the last command, HEAD must point at origin/branch. – knittl Oct 18 '12 at 18:10
  • fyi, i did this to revert the master branch and it cleared commits i had in other branches. luckily i thought to copy my web folder before doing this. – Gavin Oct 10 '13 at 21:41
  • 1
    @Gavin: no, this will under no circumstances affect other branches than `origin/branch`. Never. – knittl Oct 11 '13 at 09:23
  • @knittl how would you it if you want all your branches on remote to have equal values with the one you have locally in a single command? is this possible? – lorraine batol Oct 16 '14 at 06:42
  • @yin03: `git push origin +branch1 +branch2 +branchN`, will push all branches you specify. With a globbing refspec (something like `refs/*:refs/*`) you would be able to push all local branches without naming them explicitely (and also create the missing ones) – knittl Oct 16 '14 at 06:44
  • 1
    @greggles I know this is _very_ late but for other people wondering why that might happen, this approach will only work if you have a branch checked out. It did not work for you because you were in [detached HEAD state](https://www.git-tower.com/learn/git/faq/detached-head-when-checkout-commit), (HEAD points at a commit, not a branch) and these commands only work if HEAD is pointing at a branch. When you do `git reset` while HEAD is pointing at a branch, that branch will follow. – Michael Dorst Nov 12 '19 at 07:56
65

What I do when I mess up my local branch is I just rename my broken branch, and check out/branch the upstream branch again:

git branch -m branch branch-old
git fetch remote
git checkout -b branch remote/branch

Then if you're sure you don't want anything from your old branch, remove it:

git branch -D branch-old

But usually I leave the old branch around locally, just in case I had something in there.

Casey Marshall
  • 934
  • 7
  • 13
  • 6
    This seems like the best answer. It helps create a backup copy just in case and seems very likely to result in the local branch being an exact copy of the remote one. – greggles Oct 18 '12 at 15:59
  • Great answer, useful to me. One Q: The official git-checkout documentation seems to say that your 3rd command should be: `git checkout -b --track /` Does yours work equally well, without the `--track` ? – Starman Dec 12 '17 at 19:47
  • 1
    I think the config var `branch.autoSetupMerge` (which I think defaults to true) makes the `--track` implicit. And, yes, in all my git setups I don't need to explicitly `--track` when doing a `checkout -b`, but YMMV. – Casey Marshall Dec 13 '17 at 20:54
5

Your local branch likely has modifications to it you want to discard. To do this, you'll need to use git reset to reset the branch head to the last spot that you diverged from the upstream repo's branch. Use git branch -v to find the sha1 id of the upstream branch, and reset your branch it it using git reset SHA1ID. Then you should be able to do a git checkout to discard the changes it left in your directory.

Note: always do this on a backed-up repo. That way you can assure you're self it worked right. Or if it didn't, you have a backup to revert to.

Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69
  • This feels like it would probably work, but given the simplicity and reliability of the approach of "make a copy of your work somewhere else, make a fresh copy of the remote branch" I fail to see how this is better. – greggles Oct 18 '12 at 15:55
1
git reset --hard

This is to revert all your local changes to the origin head

Kjartan
  • 18,591
  • 15
  • 71
  • 96