32

I have to admit that I haven't played with gits advanced features but on my current project I had to.

The situation: Someone tried to implement some features and comitted them to the master, now I was called to do what this other person tried to do (but failed), therefore, the first thing I did was

git checkout -b clean_start HASH

Hash is a correct SHA1 hash of about 20 commits before the current master and that worked. I now made some changes to this branch and am now at a point where I'd like to change the current master branch of remote repository (that has the changes made by the other person) to my local branch.

In other words, I'd like to move the head of the master 20 commits back and then merge my new clean branch into it.

Is that exactly what I have to do? With revert HEAD~20 etc. or is there a command that makes exactly such a head move?

Maxem
  • 2,634
  • 1
  • 20
  • 14

3 Answers3

29

You can do this, if the remote repository accepts forced pushes:

git push --force origin clean_start:master

Note that if anyone else has the repository cloned, a push from them could potentially undo this. If you want to merge your local master branch and the remote master branch, but keep the file tree from your branch (discarding the file tree of origin's master), you can do so like this:

git merge -s ours --no-commit origin/master
git commit  # Separate step so that you can use your own commit message.
git checkout master
git merge clean_start  # Fast-forward
git push origin master

This will create a merge commit with both branches (your master and origin's master) as its parent, but the tree will be identical to your current branch tip. In other words, it will create a symbolic merge where no actual code merge occurred.

If you don't mind that other people working in the repo will be interrupted, you can use the first approach. But if you work with other people who already have these commits, the second approach will be more fool-proof and will keep history.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Yes, I forgot that he was developing from a second branch, not master. I updated my other list of commands to compensate for this oversight as well. – cdhowie Nov 25 '10 at 01:39
26
  1. You can specifically point master to where you want it to be with:

    git update-ref refs/heads/master clean_start
    

    (if you are tracking the new changes in clean_start and want master to point there)

    Beware that whatever master was pointing to (about 20 commits worth) will be "lost".

    You will need to force the push of master because of this:

    git push origin master -f
    
  2. If you want to leave your local master where it is instead and push clean_start's place to the remote master, just do this:

    git push origin clean_start:master -f

    hope this helps.

    PS. Run gitk --all & first so you can see what's going on visually as you do this.

jokklan
  • 3,520
  • 17
  • 37
Adam Dymitruk
  • 124,556
  • 26
  • 146
  • 141
17

The git reset command exists to change what HEAD points to.

In your case, you can do this:

git checkout master              # switch to the master branch
git reset --hard clean_start     # point HEAD to the clean_start branch
git push -f origin master:master # force push the new HEAD to server
jtdubs
  • 13,585
  • 1
  • 17
  • 12
  • I think this is the best answer because it also solves the local issue : you definitely want to end up with local/master pointing to the new HEAD – Titou Mar 15 '17 at 14:13