Search code examples
gitmergegit-reset

Git: Effect of reset --hard on future merging


We accidentally committed sha XXX to branch A instead of B.

A: VVV-WWW-XXX
B: VVV-WWW

So we'll follow the guidance on SO to move the commit from A to B:

git checkout B
git merge A
git checkout A
git reset --hard HEAD~1
git push --force

That will get us to:

A: VVV-WWW
B: VVV-WWW-XXX

If we then do commit YYY on branch A giving us:

A: VVV-WWW-YYY
B: VVV-WWW-XXX

And merge that into B will that cleanly merge YYY into B while not reverting XXX on B due to the fact that XXX was reset --hard previously on A? What we'd want following the merge is:

A: VVV-WWW-YYY
B: VVV-WWW-XXX-YYY

I'm struggling with the affect of reset --hard on the merging behavior. I think that reset wipes any history of the commit so the merge would just work without attempting to remove XXX from B.


Solution

  • The result of the merge will be

                    (A)
    VVV --- WWW --- YYY
              \         \   (B)
                --- XXX --- ZZZ
    

    Where ZZZ is merge commit whose parents are XXX and YYY. The single letters in parentheses represent refs or branch names, which are merely signposts along the way in a history graph.

    As rendered with git lola (a handy alias for git log --graph --decorate --pretty=oneline --abbrev-commit --all)

    *   78d2930 (HEAD -> B) ZZZ
    |\
    | * 549c09e (A) YYY
    * | f585976 XXX
    |/
    * 537d898 WWW
    * 875611c VVV
    

    I used commit messages above to tie to the history in your question. Your SHA-1 object names will differ from those above.

    Don’t overthink it. Keep in mind that git stores snapshots of tree states, and historical pedigree comes from the commit objects. Using the sharp tool git reset --hard removes history as though it never occurred with no trails left behind.

    Like any sharp tool, git reset --hard can cut you if you aren’t careful. Think about it like rm -rf.