Git: --force-with-lease and several pushurls

I have a git repository with remote origin mirroring on 3 hosts.

 $ git remote -v origin git@github.com:username/repo.git (fetch) origin git@github.com:username/repo.git (push) origin git@gitlab.com:username/repo.git (push) origin git@bitbucket.org:username/repo.git (push) 

Everything, everywhere there is commit A.

 $ git rev-parse HEAD A $ cat .git/refs/remotes/origin/master A 

I create commit B and push it. Now everything is at fixing B.

 $ git push origin master To github.com:username/repo.git A...B master -> master To gitlab.com:username/repo.git A...B master -> master To bitbucket.org:username/repo.git A...B master -> master $ git rev-parse HEAD B $ cat .git/refs/remotes/origin/master B 

Now I notice an error in the last commit, so I fix and fix the commit. This will prevent me from syncing with the remote control.

 $ git rev-parse HEAD C $ cat .git/refs/remotes/origin/master B 

I like to avoid blindly pressing --force , so I use --force-with-lease , but this is not so interesting.

 $ git push --force-with-lease origin master To github.com:username/repo.git + B...C master -> master (forced update) To gitlab.com:username/repo.git ! [rejected] master -> master (stale info) To bitbucket.org:username/repo.git ! [rejected] master -> master (stale info) 

The problem is that --force-with-lease will only consider push-safe if the remote ref has the same commit as the last time I talked to it, and my local records are sha1 of that commit in .git/refs/remotes/origin/master . Once the first mirror (GitHub) is updated, git will update my local remote ref to commit C , as a result of which push attempts on GitLab and Bitbucket will fail, as we now expect them to be in commit C.

I want to understand this, so first I force the GitHub mirror back to commit B.

 $ git push origin +B:refs/heads/master To github.com:username/repo.git + C...BB -> master (forced update) Everything up-to-date Everything up-to-date 

Now I need to be more specific as to what kind of fixation I expect the remote controls to press. The documentation says that you can specify exactly which ref to update, and what kind of commit you expect it to be with --force-with-lease=<refname>:<expect> at the moment, so I will try this.

 $ git push --force-with-lease=origin/master:B origin master To github.com:username/repo.git ! [rejected] master -> master (non-fast-forward) To gitlab.com:username/repo.git ! [rejected] master -> master (non-fast-forward) To bitbucket.org:username/repo.git ! [rejected] master -> master (non-fast-forward) 

It’s clear that I am doing something wrong. Maybe I have a <refname> error? I feel that I'm so close. What am I missing?

+8
git
source share
1 answer

Very interesting question! I tried this and successfully reproduced what you are describing with Git 2.11.0 in these test repositories:

I was able to successfully click --force-with-lease on both remote URLs using the following form:

 git push --force-with-lease origin +master 

Note the + sign in front of the branch name. Here is the result:

 $ git push --force-with-lease origin +master Counting objects: 2, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 232 bytes | 0 bytes/s, done. Total 2 (delta 0), reused 0 (delta 0) To github.com:hkdobrev/git-test.git + 099b95f...08c7548 master -> master (forced update) Counting objects: 2, done. Delta compression using up to 4 threads. Compressing objects: 100% (2/2), done. Writing objects: 100% (2/2), 232 bytes | 0 bytes/s, done. Total 2 (delta 0), reused 0 (delta 0) To github.com:hkdobrev/git-test2.git + 099b95f...08c7548 master -> master (forced update) 

On the git-push (1) man page:

Note that --force applies to all refs that are popped, therefore, using it with push.default set for mapping or with multiple push directions configured with remote.*.push can overwrite links other than the current branch ( including local links, which are strictly behind their remote counterpart). To force pushing only one branch, use + before refspec to push (e.g. git push origin +master to force push to master branch). See the <refspec>... section for more details.

+3
source share

All Articles