Search code examples
gitgit-mergegit-pullgit-merge-conflict

Force git pull to resolve divergent by discard all local commits?


The question

I have a local repo with 3 commits:

A -> B -> C

And the remote repo has another 3 commits:

A -> B -> D

How to make git pull to resolve the divergent by discarding all local commits? The local repo after git pull --some-magic should be:

A -> B -> D

Note that, git reset HEAD~1 --hard won't work, because my script doesn't know how many commits must be reverted to avoid a conflict.

Why I need this

I'm writing a script to sync between github and gitlab repositories. One of them is a read-only mirror. My scripts just try git pull --force from origin1 and git push to origin2.

However, if someone changed the history of origin1, the git pull in my script would fail with an error message. The only way to solve the problem is delete the whole local repository, and perform git clone from stretch. It's wasting bandwidth and slow!


Solution

  • You should not do this with git pull, because git pull is designed for a different purpose: to combine work. But you don't want to combine work; you want to mirror their latest commit.

    To achieve that, simply run git fetch to obtain their latest commit, then use git reset --hard to reset your local branch to their latest commit. The only tricky part is that git reset --hard demands the identity of their latest commit. That's available to you: if you know that your local branch name is main because their branch name is main, your own Git will have updated your origin/main, so you can use git reset --hard origin/main.

    Alternatively, you can use the upstream setting of the current branch:

    git reset --hard @{upstream}
    

    Note that this will throw out both committed and uncommitted work, so be careful with it.