Git: - force-with-lease和multiple pushurls

时间:2016-09-26 00:26:33

标签: git

我有一个git repo,远程origin镜像在3台主机上。

$ 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)

一切都在提交 A

$ git rev-parse HEAD
A

$ cat .git/refs/remotes/origin/master
A

我作者提交 B 并推送它。现在每个人都在提交 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

现在我注意到最后一次提交中的一个错误,所以我修复它并修改提交。这使我与遥控器不同步。

$ git rev-parse HEAD
C

$ cat .git/refs/remotes/origin/master
B

我喜欢盲目地--force推动,所以我使用--force-with-lease,但这会以一种有趣的方式失败。

$ 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)

问题是,--force-with-lease只会考虑推送安全,如果远程引用与我上次与之通信时的提交相同,并且我的本地在.git/refs/remotes/origin/master中记录了该提交的sha1 。第一个镜像(GitHub)更新后,git会更新我本地的远程引用以提交 C ,导致GitLab和Bitbucket的推送尝试失败,因为我们已经现在期望他们处于提交 C

我想弄清楚这一点,所以首先我强制GitHub镜像提交 B

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

现在我需要更具体地说明我希望遥控器用于推送的提交。文档说明你可以确切地指定要更新的引用,以及你期望它与--force-with-lease=<refname>:<expect>当前所处的提交,所以我试试。

$ 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)
显然,我做错了什么。也许我的<refname>错了?我觉得我很近。我错过了什么?

2 个答案:

答案 0 :(得分:4)

非常有趣的问题!我已经尝试过并在这些测试回购中成功地复制了你用Git 2.11.0描述的内容:

我可以使用以下格式成功地将--force-with-lease推送到两个远程网址:

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

注意分支名称前面的+符号。这是输出:

$ 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)

来自git-push (1)手册页:

  

请注意,--force适用于所有推送的引用,因此将push.default设置为匹配或与多个推送目标一起使用              配置为remote.*.push可能会覆盖当前分支以外的引用(包括严格位于其远程后面的本地引用)              对方)。要强制推送到一个分支,请使用refspec前面的+进行推送(例如git push origin +master以强制推送到master              科)。有关详细信息,请参阅上面的<refspec>...部分。

答案 1 :(得分:1)

我想到的是

git push --force-with-lease=`git rev-parse --abbrev-ref @{u} | sed 's![^/]*/!!'`:@{u}

哪里

  • git rev-parse --abbrev-ref @{u} | sed 's![^/]*/!!' 获取远程分支名称(不带远程名称)
  • @{u} 是我们期望远程分支所在的提交

我还尝试将 + 规范设为 suggested by Haralan Dobrev,但能够使用它覆盖更改。因此,我认为 + 规范应该在此处使用,因为它equals a normal force push