git push --force-with-lease 与 --force

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52823692/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:20:48  来源:igfitidea点击:

git push --force-with-lease vs. --force

gitgit-push

提问by Alexander Mills

I am trying to understand the difference between

我试图理解两者之间的区别

git push --force

and

git push --force-with-lease

My guess is that the latter only pushes to the remote if the remote does not have commits that the local branch doesn't have?

我的猜测是,如果远程没有本地分支没有的提交,后者只会推送到远程?

回答by chevybow

forceoverwrites a remote branch with your local branch.

force用您的本地分支覆盖远程分支。

--force-with-leaseis a safer option that will not overwrite any work on the remote branch if more commits were added to the remote branch (by another team-member or coworker or what have you). It ensures you do not overwrite someone elses work by force pushing.

--force-with-lease是一个更安全的选项,如果将更多提交添加到远程分支(由另一个团队成员或同事或您拥有的东西),则不会覆盖远程分支上的任何工作。它确保您不会通过强制推送覆盖其他人的工作。

I think your general idea surrounding the command is correct. If the remote branch has the same value as the remote branch on your local machine- you will overwrite remote. If it doesn't have the same value- it indicates a change that someone else made to the remote branch while you were working on your code and thus will not overwrite any code. Obviously if there are additional commits in remote then the values won't be the same.

我认为您对命令的总体看法是正确的。如果远程分支与本地机器上的远程分支具有相同的值 - 您将覆盖 remote。如果它没有相同的值 - 它表示其他人在您处理代码时对远程分支进行了更改,因此不会覆盖任何代码。显然,如果远程中有其他提交,则值将不相同。

I just think of --force-with-leaseas the option to use when I want to make sure I don't overwrite any teammates code. A lot of teams at my company use --force-with-leaseas the default option for a fail-safe. Its unnecessary in most circumstances but will save you lots of headache if you happen to overwrite something that another person contributed to remote.

--force-with-lease当我想确保我不会覆盖任何队友代码时,我只是想使用这个选项。我公司的许多团队都将其--force-with-lease用作故障安全的默认选项。在大多数情况下它是不必要的,但是如果您碰巧覆盖了另一个人为远程贡献的内容,则会为您省去很多麻烦。

I'm sure you looked at the docs but there might be some more wordy explanation contained in here:

我确定您查看了文档,但此处可能包含一些更冗长的解释:

https://git-scm.com/docs/git-push

https://git-scm.com/docs/git-push

回答by VonC

Looking for an answer drawing from credible and/or official sources.

寻找来自可靠和/或官方来源的答案。

The "compare and swap" mentioned by torekin the commentsand in his other answeris further illustrated by the sources of Git itself.

torek评论他的其他答案中提到的“比较和交换”由Git 本身来源进一步说明。

the latter only pushes to the remote if the remote does not have commits that the local branch doesn't have?

如果远程没有本地分支没有的提交,后者只会推送到远程?

That feature was introduced in this commit(Dec. 2013, Git v1.8.5-rc0)

该功能在此提交中引入(2013 年 12 月,Git v1.8.5-rc0)

--force-with-leasewill protect all remote refs that are going to be updated by requiring their current value to be the same as some reasonable default, unless otherwise specified;

For now, "some reasonable default" is tentatively defined as "the value of the remote-tracking branch we have for the ref of the remote being updated", and it is an error if we do not have such a remote-tracking branch.

--force-with-lease除非另有说明,否则将通过要求它们的当前值与某些合理的默认值相同来保护所有将要更新的远程引用;

目前,“一些合理的默认值”被暂时定义为“我们拥有的远程跟踪分支的值,用于更新远程的引用”,如果我们没有这样的远程跟踪分支,这是一个错误。

So "lease" means:

所以“租赁”的意思是:

"force-with-lease": You assume you took the lease on the ref when you fetched to decide what the rebased history should be, and you can push back only if the lease has not been broken.

" force-with-lease": 你假设你在获取时已经租用了 ref 来决定重新定位的历史应该是什么,并且只有在租约没有被破坏的情况下你才能推迟。

The sources still mentions "cas":

消息来源仍然提到“cas”:

  • This option was originally called "cas" (for "compare and swap"), the name which nobody liked because it was too technical.
  • The second attempt called it "lockref" (because it is conceptually like pushing after taking a lock) but the word "lock" was hated because it implied that it may reject push by others, which is not the way this option works.
  • This round calls it "force-with-lease".
    You assume you took the lease on the ref when you fetched to decide what the rebased history should be, and you can push back only if the lease has not been broken.
  • 这个选项最初被称为“ cas”(表示“比较和交换”),这个名字没有人喜欢,因为它太技术性了。
  • 第二次尝试将其称为“lockref”(因为它在概念上类似于在获取锁后推送)但是“锁”这个词被讨厌,因为它暗示它可能会拒绝其他人的推送,这不是此选项的工作方式。
  • 这一轮称之为“强制租赁”。
    您假设您在获取时租用了 ref 以决定重新定位的历史记录应该是什么,并且只有在租用未被破坏的情况下才能推迟。

So: "git push --force-with-leasevs. --force"

所以:“git push --force-with-lease--force

As I mentioned in "push --force-with-leaseby default", as Git 2.13 (Q2 2017) mentions, that the option --force-with-leasecan be ignoredif a background process (like the ones you find in an IDE with a Git plugin) runs git fetch origin.
In that case, --forceprevails.

正如我在“push --force-with-lease默认情况下”中提到的,正如 Git 2.13(2017 年第二季度)所提到的,如果后台进程(例如您在带有 Git 插件的 IDE 中找到的进程)运行,则--force-with-lease可以忽略该选项git fetch origin
在这种情况下,--force占上风。

回答by Shakil

git push --forceis destructive because it unconditionally overwrites the remote repository with whatever one have locally. git's push --forceis strongly discouraged as it can destroy other commits already pushed to a shared repository. One of the most common causes of force pushes is when we're forced to rebase a branch.

git push --force是破坏性的,因为它无条件地用本地的任何内容覆盖远程存储库。强烈建议不要使用git 的push --force,因为它会破坏已经推送到共享存储库的其他提交。强制推送的最常见原因之一是当我们被迫重新设置分支时。

For example. We have a project with a feature branch that both Alice and Bob are going to work on. They both clone this repository and start work. Alice initially completes her part of the feature, and pushes this up to the main repository. This is all well and good. Bob also finishes his work, but before pushing it up he notices some changes had been merged into master. Wanting to keep a clean tree, he performs a rebase against the master branch. Of-course, when he goes to push this rebased branch it will be rejected. However not realising that Alice has already pushed her work, he performs a push --force. Unfortunately, this will erase all record of Alice's changes in the central repository.

例如。我们有一个带有功能分支的项目,Alice 和 Bob 都将在该项目上工作。他们都克隆了这个存储库并开始工作。Alice 最初完成了她的部分功能,并将其推送到主存储库。这一切都很好。Bob 也完成了他的工作,但在推动它之前,他注意到一些更改已合并到 master 中。为了保持一棵干净的树,他对主分支执行了变基。当然,当他去推送这个 rebase 的分支时,它会被拒绝。然而没有意识到 Alice 已经推动了她的工作,他执行了 push --force。不幸的是,这将删除 Alice 在中央存储库中的所有更改记录。

What --force-with-leasedoes is refuse to update a branch unless it is the state that we expect; i.e. nobody has updated the branch upstream. In practice this works by checking that the upstream ref is what we expect, because refs are hashes, and implicitly encode the chain of parents into their value.

什么--force-与租赁确实是垃圾更新某个分支,除非它是我们所期望的状态; 即没有人更新上游分支。在实践中,这是通过检查上游 ref 是否符合我们的预期来实现的,因为 ref 是散列,并将父链隐式编码为它们的值。

Hereis a good post regarding git push --force and git push --force-with-lease.

是一篇关于 git push --force 和 git push --force-with-lease 的好帖子。

回答by G. Sylvie Davies

Assuming any pre-receive hooks on the server accept the push, this will always succeed:

假设服务器上的任何 pre-receive 钩子接受推送,这将始终成功:

git push --force

Whereas this runs a specific client-side check before proceeding:

而这会在继续之前运行特定的客户端检查:

git push --force-with-lease

You can run the specific check yourself manually. Here's the "lease-checking" algorithm:

您可以自己手动运行特定检查。这是“租约检查”算法:

  1. Figure out your current branch.

  2. Run git for-each-ref refs/remotes. Take note of the commit-id your git client thinks corresponds to the upstream state of your current branch.

  1. 找出你当前的分支。

  2. 运行git for-each-ref refs/remotes。记下您的 git 客户端认为对应于您当前分支的上游状态的 commit-id。

E.g., if you are on branch "foo", take note of the commit-id associated with "refs/remotes/origin/foo".

例如,如果您在分支“foo”上,请注意与“refs/remotes/origin/foo”相关联的提交 ID。

  1. Determine the actual commit-id of the remote branch on the upstream git server right now.

  2. Only let the "git push" proceed if the commit-ids you extracted from step 2 and step 3 agree. In other words, only proceed if your local git clone's notion of upstream agrees with actual upstream.

  1. 立即确定上游 git 服务器上远程分支的实际提交 ID。

  2. 如果您从第 2 步和第 3 步中提取的提交 ID 一致,则仅让“git push”继续进行。换句话说,只有当您本地 git clone 的上游概念与实际上游一致时才继续。

There's a sad implication here: since git fetchupdates all refs under "refs/remotes/origin/*" to their latest versions, this combination of commands is essentially identical to git push --force:

这里有一个可悲的含义:由于将git fetch“refs/remotes/origin/*”下的所有 refs 更新为最新版本,因此这种命令组合本质上等同于git push --force

git fetch

# The command below behaves identically to "git push --force"
# if a "git fetch" just happened!

git push --force-with-lease

To work around this inherent weakness in git push --force-with-leaseI try to never run git fetch. Instead I always run git pull --rebasewhenever I need to sync with upstream, since git pullonly updates a single ref under refs/remotes, keeping the "lease" of --force-with-leaseuseful.

为了解决这个固有的弱点,git push --force-with-lease我尽量不要跑步git fetch。相反,我总是git pull --rebase在需要与上游同步时运行,因为git pull只更新 refs/remotes 下的单个 ref,保持“租约”--force-with-lease有用。

回答by Fish

Force-with-lease is not necessarily safe. It just works as Sylvie said. One note: In git a branch is just a pointer on a commit. And commits point to zero or more parent commits. Even if you changed the branch entirely with a hard git reset and a forced push or a push with - - force-with-lease without wanting it, that's not necessarily a big problem. You can use your local git reflog to see how your local tip on the branches (Where was HEAD at that time? ) has changed and reset and push the branch again. Then you only lose new commits on the remote branch, but even they might be restored by the team members.

强制租赁不一定安全。它就像 Sylvie 所说的那样有效。一个注意事项:在 git 中,分支只是提交上的一个指针。并且提交指向零个或多个父提交。即使您在不想要它的情况下使用硬 git reset 和强制推送或使用 --force-with-lease 推送完全更改了分支,这也不一定是大问题。您可以使用本地 git reflog 来查看分支上的本地提示(当时 HEAD 在哪里?)如何更改并重置并再次推送分支。然后你只会丢失远程分支上的新提交,但即使它们也可能被团队成员恢复。