git - git 创建远程分支而不破坏任何现有分支
问题描述
我想在本地和远程创建一个开发分支,而不会意外干扰其他任何人的开发分支。创建本地分支很容易,并且不会受到任何竞争条件的影响,但是安全地创建远程分支却很棘手。
假设我想创建一个名为 的分支cleanup
,但其他人可能有相同的想法并cleanup
在我之前创建了自己的分支。如果我简单地说git push --set-upstream origin cleanup
,也许它会创建一个新的远程分支,或者它可能会快进一个已经存在的分支。
如果远程分支已经存在,我想git push ...
失败,所以我可以选择不同的分支名称。
我已经知道几个不完美的解决方案,比如git fetch
然后快速推动;这仍然受制于比赛条件。或者做一个git push
,注意命令输出中是否存在远程分支,然后尝试从不良情况中恢复;这很混乱,并且在恢复过程中会受到更糟糕的比赛条件的影响。也可以以git push --force-with-lease
各种方式使用来做类似的事情,但我最接近解决问题的方法是拒绝创建分支而不是快速转发,这与我的目标相反。
更新:理想情况下,解决方案不会依赖于树中文件的数量或 git 历史记录的长度的算法复杂性。需要对 repo 进行新克隆或删除并重新签出工作树中的所有文件的解决方案是不可接受的。
解决方案
function git-new-branch() {
# usage: git-new-branch branchname
git push origin $(git commit-tree -m "" $(git mktree <&-) <&-):refs/heads/$1 || return 1
git checkout -b $1
git push --set-upstream --force-with-lease origin $1
}
解释
git mktree
并git commit-tree
读取标准输入,因此用于<%-
关闭这些进程的标准输入。
是幂等的git mktree
并打印空树的 sha1。
使用git commit-tree
空树进行空提交,重要的是该提交没有父母。git commit-tree
也打印一个 sha1,但它不是幂等的。提交有你的user.name
和一个时间戳。.git
此外,此提交作为孤立提交进入目录。孤立的提交最终将被git
自动垃圾收集;见git help gc
。这-m ""
意味着提交消息将为空。但是这些都不重要,因为这个提交将被使用一次并立即被放弃。
第一个git push
将空提交推送到您提供的分支名称。如果分支已经存在,则保证被拒绝,因为空提交没有父母,因此推动它不可能导致快进。(并且由于每次调用都会重新生成提交,因此提交不可能已经在任何地方的远程仓库中。)
|| return 1
如果命令失败,将中止该功能。
git checkout -b
该命令没有错误检查。此函数假定您还没有具有给定名称的本地分支。
第二个git push
使用--force-with-lease
,这意味着只有当它仍然是我们认为的那样时,才会更新远程分支,也就是我们刚刚推送的空提交。
学分
感谢 o11c 和 jthill 的回答为这个解决方案提供了灵感。
推荐阅读
- javascript - 在回调中丢失上下文
- javascript - 关闭时保存本地?
- c++ - opencv如何获得轮廓的中线
- ruby-on-rails - Rails 迁移停止,即使表不存在
- excel - Range.Find 适用于单个单元格,但在循环时会跳过它
- javascript - 澄清 - 为什么我们需要将嵌套的 async/await 包装在另一个 async/await 中?
- python - 查询 MongoDB 以获取作为数组元素的单个嵌入文档
- r - 使用 pipe() 函数提取列表的元素
- r - 在 R 中运行带有滞后工具的简单 GMM
- azure - 消费中如何将Azure功能放在同一个应用服务计划中?