git push --force-with-lease
这个命令,它非常棒。但是,我并不经常使用强制推送,所以我担心下次需要用到这个好用的功能时会忘记。有没有一种方法可以配置git,让
git push -f
自动使用--force-with-lease
,除非我故意用--no-force-with-lease
来覆盖它?(我无法想象什么情况下会想要使用不带租约的force!)
git push --force-with-lease
这个命令,它非常棒。但是,我并不经常使用强制推送,所以我担心下次需要用到这个好用的功能时会忘记。git push -f
自动使用--force-with-lease
,除非我故意用--no-force-with-lease
来覆盖它?目前还没有办法在git中配置默认使用force-with-lease
而不是force
,因此最好的选择是创建一个别名来实现这个目的。
编辑 这仍然适用于2022年5月。但是git 2.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 存储库中的文档目录。在这里,您可以找到编码指南和有关如何提交补丁的信息。
您可以在官方社区页面上找到所有这些链接以及更多链接。
我的解决方案是创建一个包装脚本,并使用别名以便我始终在实际的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
将起作用。-f
git
~/.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
现在应该会在您尝试强制推送时变得挑剔。
git push --force
,因为只要在进行git push --force-with-lease
之前执行git fetch
,就可以始终成功。 - Ragasgit push --force-with-lease
是否总是安全的?”中提到了这个新选项。
git push --force-if-includes
Add a check to verify if the remote-tracking ref of the local branch is reachable from one of its "reflog" entries.
Alexey Romanov在评论中提到:
"何时应该使用"git push --force-if-includes
",其中添加了更多细节。
avar
)完成。gitster
--在提交 46bdfa3中合并,2017年4月26日)
文档和测试用例,其中存在两个指向相同URL的远程仓库,并且后台获取和随后的
push
:使用多个远程仓库文档和测试--force-with-lease
git push --force-with-lease
不应该覆盖我们尚未获取的未更新引用。--force-with-lease
和--force-with-lease=<refname>
提供的保护措施,正如此处添加的文档中所述。general note on safety: supplying this option without an expected value, i.e. as
--force-with-lease
or--force-with-lease=<refname>
interacts very badly with anything that implicitly runsgit fetch
on the remote to be pushed to in the background, e.g.git fetch origin
on your repository in a cronjob.The protection it offers over
--force
is ensuring that subsequent changes your work wasn't based on aren't clobbered, but this is trivially defeated if some background process is updating refs in the background. We don't have anything except the remote tracking info to go by as a heuristic for refs you're expected to have seen & are willing to clobber.If your editor or some other system is running
git fetch
in the background for you, a way to mitigate this is to simply set up another remote:git remote add origin-push $(git config remote.origin.url) git fetch origin-push
Now when the background process runs
git fetch origin
the references onorigin-push
won't be updated, and thus commands like:git push --force-with-lease origin-push
Will fail unless you manually run
git fetch origin-push
.
This method is of course entirely defeated by something that runsgit fetch --all
, in that case you'd need to either disable it or do something more tedious like:
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
I.e. create a
base
tag for versions of the upstream code that you've seen and are willing to overwrite, then rewrite history, and finally force push changes tomaster
if the remote version is still atbase
, regardless of what your localremotes/origin/master
has been updated to in the background.
--force-if-includes
来解决--force-with-lease
这个问题。参考链接:https://dev59.com/DVEG5IYBdhLWcg3wcuD2 - Alexey Romanov我想提醒自己不要使用-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
中。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
中。git push -f
的参数。 - neu242-f | --force
参数并保留其他参数(fn() { if [[ $1 == 'push' ]]; then command echo fn "${@/(-f|--force)/--force-with-lease}"; else command echo fn "$@"; fi; }
),但我无法将其替换为整个单词,因此它会将--follow-tags
替换为---force-with-leaseollow-tags
。有什么建议吗? - paulodiovaniggfl
命令。gpf
。 - JamesWilson
rm
别名为.bashrc
中的rm -i
一样;你会忘记,在服务器上删除一个重要文件。采用自己的别名就不存在这个问题 :) - hrabanpushf
,但总是仔细检查自己是否没有执行push -f
,因为它看起来很像这个别名。一些团队成员仍然使用push -f
,认为别名只是一个化妆品上的缩写。最终,我们将更安全的形式别名为pushfl
,并停止担心它。 - kelvin