Asked  6 Months ago    Answers:  5   Viewed   352 times

I want to push my local files, and have them on a remote repo, without having to deal with merge conflicts. I just want my local version to have priority over the remote one.

How can I do this with Git?

 Answers

23

You should be able to force your local revision to the remote repo by using

git push -f <remote> <branch>

(e.g. git push -f origin master). Leaving off <remote> and <branch> will force push all local branches that have set --set-upstream.

Just be warned, if other people are sharing this repository their revision history will conflict with the new one. And if they have any local commits after the point of change they will become invalid.

Update: Thought I would add a side-note. If you are creating changes that others will review, then it's not uncommon to create a branch with those changes and rebase periodically to keep them up-to-date with the main development branch. Just let other developers know this will happen periodically so they'll know what to expect.

Update 2: Because of the increasing number of viewers I'd like to add some additional information on what to do when your upstream does experience a force push.

Say I've cloned your repo and have added a few commits like so:

            D----E  topic
           /
A----B----C         development

But later the development branch is hit with a rebase, which will cause me to receive an error like so when I run git pull:

Unpacking objects: 100% (3/3), done.
From <repo-location>
 * branch            development     -> FETCH_HEAD
Auto-merging <files>
CONFLICT (content): Merge conflict in <locations>
Automatic merge failed; fix conflicts and then commit the result.

Here I could fix the conflicts and commit, but that would leave me with a really ugly commit history:

       C----D----E----F    topic
      /              /
A----B--------------C'  development

It might look enticing to use git pull --force but be careful because that'll leave you with stranded commits:

            D----E   topic

A----B----C'         development

So probably the best option is to do a git pull --rebase. This will require me to resolve any conflicts like before, but for each step instead of committing I'll use git rebase --continue. In the end the commit history will look much better:

            D'---E'  topic
           /
A----B----C'         development

Update 3: You can also use the --force-with-lease option as a "safer" force push, as mentioned by Cupcake in his answer:

Force pushing with a "lease" allows the force push to fail if there are new commits on the remote that you didn't expect (technically, if you haven't fetched them into your remote-tracking branch yet), which is useful if you don't want to accidentally overwrite someone else's commits that you didn't even know about yet, and you just want to overwrite your own:

git push <remote> <branch> --force-with-lease

You can learn more details about how to use --force-with-lease by reading any of the following:

  • git push documentation
  • Git: How to ignore fast forward and revert origin [branch] to earlier commit?
Tuesday, June 1, 2021
 
edorian
answered 6 Months ago
38

? Important: If you have any local changes, they will be lost. With or without --hard option, any local commits that haven't been pushed will be lost.
  • If you have any files that are not tracked by Git (e.g. uploaded user content), these files will not be affected.


    First, run a fetch to update all origin/<branch> refs to latest:

    git fetch --all
    

    Backup your current branch:

    git branch backup-master
    

    Then, you have two options:

    git reset --hard origin/master
    

    OR If you are on some other branch:

    git reset --hard origin/<branch_name>
    

    Explanation:

    git fetch downloads the latest from remote without trying to merge or rebase anything.

    Then the git reset resets the master branch to what you just fetched. The --hard option changes all the files in your working tree to match the files in origin/master


    Maintain current local commits

    [*]: It's worth noting that it is possible to maintain current local commits by creating a branch from master before resetting:

    git checkout master
    git branch new-branch-to-save-current-commits
    git fetch --all
    git reset --hard origin/master
    

    After this, all of the old commits will be kept in new-branch-to-save-current-commits.

    Uncommitted changes

    Uncommitted changes, however (even staged), will be lost. Make sure to stash and commit anything you need. For that you can run the following:

    git stash
    

    And then to reapply these uncommitted changes:

    git stash pop
    
    Tuesday, June 1, 2021
     
    xrock
    answered 6 Months ago
    48

    The conditional include that I detail here is only for commit authorship (user.name/email).

    This has nothing to do with authentication (credentials: username/password)

    Those are probably cached in a credential manager (like the linux osx-keychain)
    Check the output of:

    git config credential.helper
    

    If you can, use instead SSH keys per environment, as I illustrate there: then you can easily maintain different identities for the same remote repo (github.com)


    Note: the GCM (Git Credential Manager) installed alongside Git for Windows does not, as stated in issue 363, support multiple users per Uri.

    Friday, July 30, 2021
     
    jeremyharris
    answered 4 Months ago
    54

    Use git checkout instead of git stash apply:

    $ git checkout stash -- .
    $ git commit
    

    This will restore all the files in the current directory to their stashed version.


    If there are changes to other files in the working directory that should be kept, here is a less heavy-handed alternative:

    $ git merge --squash --strategy-option=theirs stash
    

    If there are changes in the index, or the merge will touch files with local changes, git will refuse to merge. Individual files can be checked out from the stash using

    $ git checkout stash -- <paths...>
    

    or interactively with

    $ git checkout -p stash
    
    Saturday, August 7, 2021
     
    mark
    answered 4 Months ago
    59

    Perhaps the simplest answer is to rename your local branch some_branch to another name, e.g. with:

    git branch -m some_branch a_branch_name_not_present_on_some_remote
    

    The reason for this is that git push by default pushes each branch to a branch with a matching name on the remote, if such a branch exists there. If you don't like this behaviour in general, you have to change the push.default config option. For example, you could do:

    git config --global push.default tracking
    git branch --set-upstream some_branch origin/totally_different_branch
    

    I wrote a bit more here about the behaviour of git push where you don't specify the refspec explicitly.

    Monday, November 1, 2021
     
    Christian
    answered 1 Month ago
    Only authorized users can answer the question. Please sign in first, or register a free account.
    Not the answer you're looking for? Browse other questions tagged :
     
    Share