Search code examples
gitversion-controlgit-branchgit-checkout

What would be the difference between `git branch -f master HEAD~` and `git reset HEAD~`?


See title really.

Assuming we're already on the master branch:

What would be the difference between git branch -f master HEAD~ and git reset HEAD~?

As far as I can tell both of these commands move the branch/HEAD pointers one up in the commit chain, but are there any other differences between these two worth noting?


Solution

  • Assuming master is the current branch, git branch -f master HEAD~ refuses to do anything and reports the error "fatal: Cannot force update the current branch."

    If you are on a different branch, git branch -f master HEAD~ moves the branch master on the first parent of the current branch and does not affect the current branch, the index or the working tree.

    git reset HEAD~ is the same as git reset --mixed HEAD~. It moves the current branch on its first parent, updates the index to match the new position of the branch and does not affect the working tree.

    As you can see, there are many differences between the two commands.

    Please read the documentation of git branch.

    Remark: If git branch -f master HEAD~ would work when master is the current branch, its effect would probably be the same as git reset --soft HEAD~. We will never know because this form of git branch refuses to change the branch that is currently checked out.


    The OP asked in a comment: "I am also aware that mixed is a default for reset but there are also soft and hard but I don't know the differences."

    Scenario:

    1. git checkout master
    2. modify file1
    3. git add file1
    4. git commit

    After this steps:

    • git reset --soft HEAD~1 moves only the master branch where it was before the last commit; it brings the repo back to the state where it was after step 3;
    • git reset --mixed HEAD~1 moves the branch and updates the index to match it; it brings the repo to the state it was after step 2;
    • git reset --hard HEAD~1 moves the branch then updates the index and the working tree to match it; it brings the repo to the state it was after step 1.

    Of course, this is a simplified explanation and the "brings the repo to the state" parts apply only to this simplified scenario. If you git reset to a different commit then keep only the explanation about what happens to the branch, the index and the working tree and figure out how the repo will look like after each flavour of the git reset command.