默认情况下推送--force-with-lease


130

我刚刚了解到git push --force-with-lease。太棒了 但是,当然,我不经常使用武力,因此我担心下次需要时可能会忘记此漂亮功能。

有没有一种配置git的方法,除非我有意覆盖它,否则git push -f它将自动使用?--force-with-lease--no-force-with-lease

(我无法想象曾经想在没有租约的情况下使用武力!)

Answers:


141

AFAIK没有可用的配置来告诉git始终使用force-with-lease而不是force。这似乎是功能请求的一个很好的例子。如果您没有任何问题可以深入git代码库,则可以自己实现并提交以供审核。

编辑就目前而言,这在2019年4月仍然是正确的。

在那之前,我经常看到的唯一选择就是创建一个alias用于此目的的。

创建一个别名

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

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

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

弄脏你的手

如果您想自己实现该功能,但不确定从哪里开始,则首先应查看git存储库中的文档目录。在这里,您可以找到编码准则以及有关如何提交补丁的信息

您可以在官方社区页面上找到所有这些链接以及更多内容。


25
关于这不是功能的说明:反对重写标准命令(“ push --force”)的常见论点是,您已经习惯了它们,忘记了它们的起源,并且有一天有一天不小心在新系统上以这种方式使用了它们。就像混叠rmrm -i在你的.bashrc; 您有一天会忘记并删除服务器上的重要文件。使用您自己的别名不存在该问题:)
hraban

2
个人轶事/警告词:我尝试将其别名为,pushf但始终仔细检查我没有使用push -f,因为它看起来与别名相似。push -f无论如何,一些团队成员一直在使用,以为别名只是它的装饰性简写。最终,我们将更安全的表单别名pushfl改为,并不再担心它。
开尔文

31

我担心我下次需要它时可能会忘记此漂亮功能。

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

提交f17d642通过(2017年4月19日)ÆvarArnfjörðBjarmason( )avar
(由Junio C gitsterHamano合并--commit 46bdfa3中,2017年4月26日)

push--force-with-lease使用多个遥控器进行文档和测试

记录并测试以下情况:有两个指向同一URL的远程对象,并且后台获取和后续操作git push --force-with-lease不应破坏我们尚未获取的未更新引用。

一些编辑器(例如Microsoft的VSC)具有在后台自动提取的功能,这绕过了--force-with-lease&所提供的保护--force-with-lease=<refname>,如此处添加的文档所述。

因此,目前的文档git push包括:

关于安全的一般说明:提供此选项时没有期望的值,即 与隐式运行在遥控器上并在后台(例如 ,在cronjob中的存储库中)隐式运行的任何内容--force-with-lease--force-with-lease=<refname>与之交互非常差。git fetchgit fetch origin

它提供的保护措施可以--force确保您的工作所基于的后续更改不会被破坏,但是如果某些后台进程在后台更新引用,这将是微不足道的。除了远程跟踪信息以外,我们没有其他任何东西,可以启发您希望看到的参考文献,并愿意为之烦恼。

如果您的编辑器或某些其他系统git fetch在后台运行,那么减轻此问题的一种方法就是简单地设置另一个远程控制器:

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
当然,此方法被运行的东西完全击败了git fetch --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,为您已经看到并愿意覆盖的上游代码版本创建标签,然后重写历史记录,最后强制将更改推送到master远程版本是否仍处于的状态base,而不管您本地中的本地版本remotes/origin/master已更新为什么。背景。


30

我的解决方案是创建一个包装器脚本,并使用一个别名,以便始终使用它代替real 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. 创建一个自定义脚本,该脚本将通过任何参数传递给git,除了 -f
  2. 该脚本的别名,所以我们用它代替 git

这些说明假定运行bash的Linux或Mac。我尚未在zsh或Windows上尝试过此操作,但我认为它也可以在其中运行。

~/.bash_profile

alias git=~/.git_wrapper.sh

~./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现在当您尝试强制执行推送时应该会感到不适。


17
好像很方便。+1。也许将“嘿白痴”替换为“嘿,你是温柔而简单的灵魂”或类似的东西;)
VonC


3

我想提醒我不要使用-f,但是我不想被愚弄相信这-f意味着--force-with-lease。所以这是我的看法:

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

添加到您的.bash_profile.bashrc.zshrc


1

您可以创建一个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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.