缺省情况下强制租赁

我刚学了 git push --force-with-lease。太棒了。但是,当然,我不经常使用强制,所以我担心我可能会忘记这个漂亮的功能,下次我需要它。

有没有办法配置 git,使 git push -f自动使用 --force-with-lease,除非我故意用 --no-force-with-lease覆盖它?

(我无法想象没有租约就要使用武力!)

27942 次浏览

目前还没有办法将 git 配置为始终使用 force-with-lease而不是 force。因此,下一个可用的最佳选择往往是创建一个用于此目的的别名。

这在2022年5月仍然是事实。但是 GIT2.30增加了一个 附加费选项 force-if-includes,使得 force-with-lease更加安全; 检查 这个深入的答案,如果你想理解的推理

创建一个化名

要创建别名,可以使用 git config --global alias.<alias-name> <command>,在我们的例子中,我建议使用类似的方法。

git config --global alias.pushfwl "push --force-with-lease"

这将在全局 .gitconfig文件中创建一个条目(通常可以在 主目录中找到)。在此之后,您可以使用 git pushfwl强制租赁

把手弄脏

或者,您可以决定自己实现这个特性!如果您不确定从哪里开始,您可能想看看 Git 存储库中的文档 目录。在这里你可以找到 编码指引 如何 < strong > 提交补丁 的信息。

你可以找到所有这些链接和更多的 官方社区网页

我担心我可能会忘记这个漂亮的功能,下次我需要它。

Git 2.13(2017年第二季度)解释了为什么没有“保护”来防止这个推送选项被遗忘,因为即使你在 git push级别忘记了它,它仍然可能被忽略。

提交 f17d642(2017年4月19日) by 埃瓦尔 · 阿恩菲尔 · 比亚马森(avar)
(由 朱尼奥 · C · 哈马诺 gitster于2017年4月26日在 提交46bdfa3合并)

用多个遥控器记录和测试 --force-with-lease

对于有两个指向 相同的 URL,以及后台提取和随后的 git push --force-with-lease不应该重创我们没有提取的未更新的引用。

一些编辑器,如微软的 VSC 有一个功能,以自动获取在 背景,这绕过了 --force-with-lease & --force-with-lease=<refname>提供的保护,正如这里添加的文档所指出的

因此,git push的文件现在包括:

关于安全性的一般说明: 在没有预期的情况下提供此选项 值,即 --force-with-lease--force-with-lease=<refname> 与任何隐式运行 git fetch的 要推到后台的遥控器,例如 git fetch origin 在您的存储库中进行错误的操作。

它在 --force上提供的保护是确保您的工作没有基于的后续更改不会遭到破坏,但是如果某个后台进程在后台更新参考文献,那么这种保护就无足轻重了。我们没有任何东西,除了远程跟踪信息去作为一个启发式的裁判,你应该已经看到并愿意重击。

如果您的编辑器或其他系统在 对于您来说,减轻这种影响的一种方法是简单地设置另一个 遥控器:

git remote add origin-push $(git config remote.origin.url)
git fetch origin-push

现在,当后台进程运行 git fetch origin时,引用 在 origin-push上不会被更新,因此像下面这样的命令:

git push --force-with-lease origin-push

将失败,除非您手动运行 git fetch origin-push
当然,这个方法完全被运行 < code > git get 的某个程序所打败 —— all ,在这种情况下,您需要禁用它或执行某些操作 比如:

git fetch              # update 'master' from remote
git tag base master    # mark our base point
git rebase -i master   # rewrite some commits
git push --force-with-lease=master:base master:master

例如,为你已有的上游代码版本创建一个 base标签 如果远程版本仍然在 base,那么无论您的本地 remotes/origin/master在后台已经更新到什么,都可以看到并且愿意覆盖,然后重写历史记录,最后强制将更改推到 master

我的解决方案是创建一个包装器脚本,并使用一个别名,这样我总是使用它来代替真正的 git

每当我尝试 git push -f,我看到以下内容:

⚡ git push -f
use this instead so you don't cause race conditions in the
repo: git push --force-with-lease

这个脚本的一些优点是:

  • 它训练我习惯性地使用 --force-with-lease,所以当我写错的时候我不会被唠叨
  • 如果,出于某种原因,我们真的需要强制推动,git push --force将工作。

如何实施:

  1. 创建一个自定义脚本,该脚本将通过除 -f以外的任何参数传递给 git
  2. 别名的脚本,所以我们使用它而不是 git

这些指令假设运行 bash 的是 Linux 或 Mac。我还没有在 zsh 或 Windows 中尝试过这种方法,但我想它在这里也能工作。

返回文章页面

alias git=~/.git_wrapper.sh

返回文章页面

#!/bin/bash
for arg in "$@"; do
if [ "$arg" = "push" ]; then
ispush=1
elif [ "$ispush" = 1 -a "$arg" = '-f' ]; then
echo "use this instead so you don't cause race conflicts in the repo: git push --force-with-lease"
exit 1
fi
done


git "$@"

有了这些变化,重新启动您的终端和 git现在应该得到傲慢的时候,您尝试强制推。

对于使用 OMYZSH 的人,您可以简单地使用 ggfl

您可以创建一个 bash 函数来替换 git,并使用 --force-with-lease而不是 --force

# replaces `git push --force` with `git push --force-with-lease`
git() {
if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then
command git push --force-with-lease
else
command git "$@"
fi
}

或者,在一行:

git() { if [[ $@ == 'push -f'* || $@ == 'push --force'* ]]; then command git push --force-with-lease; else command git "$@"; fi; }

只要把它添加到你的 ~/.bashrc~/.zshrc

我想被提醒,我不应该使用 -f,但我不想被愚弄,以为 -f意味着 --force-with-lease。这就是我的看法:

git() {
if [[ $@ == 'push -f'* || $@ == 'push --force '*  ]]; then
echo Hey stupid, use --force-with-lease instead
else
command git "$@"
fi
}

添加到你的 .bash_profile.bashrc.zshrc