git push --force-with-lease 总是安全的吗?

Plu*_*fee 6 git

我一直遵循的规则是,一旦将 git 历史推送到远程存储库,就不要修改它。

但我想知道是否交互式变基到 push --force-with-lease 绕过了这个规则?

如果强制租赁成功,其他用户是否完全安全,或者此策略是否有任何警告?

预先感谢您提供任何意见。

Von*_*onC 16

使用 Git 2.30(2021 年第 1 季度)可以使其变得更安全:“ ( man ) ”很容易被误用而丢失提交,除非用户妥善保管自己的“ ”。git push --force-with-lease[=<ref>]git fetch

新选项“ --force-if-includes”尝试确保在检查即将被强制替换的远程引用尖端的提交后创建被强制推送的内容。

当远程跟踪引用有我们本地没有的更新时,它会拒绝分支的强制更新。

请参阅Srinidhi Kaushik ( )提交的提交 3b5bf96提交 3b990aa提交 99a1f9a(2020 年 10 月 3 日)。 请参阅Junio C Hamano ( )提交的 aed0800(2020 年 10 月 2 日)。(由Junio C Hamano 合并 -- --提交 de0a7ef中,2020 年 10 月 27 日)clickyotomy
gitster
gitster

push--force-if-includes:添加对“ ”的reflog检查

签署人:Srinidhi Kaushik

添加一项检查以验证是否可以从其“reflog”条目之一访问本地分支的远程跟踪引用。

该检查会迭代本地引用的引用日志,以查看是否存在远程跟踪引用的条目,并将看到的任何提交收集到列表中;如果引用日志中的条目与远程引用匹配,或者如果条目时间戳比远程引用的“引用日志”的最新条目更旧,则迭代停止。如果没有找到远程引用的条目,"in_merge_bases_many()则调用“来检查是否可以从收集的提交列表中访问它。

当基于远程引用的本地分支已被倒回并强制推送到远程时,“ --force-if-includes”运行检查以确保可能发生的远程跟踪引用的任何更新(通过从另一个存储库推送) )在本地分支的最后更新时间(git pull例如,通过“”)和推送时间之前,在允许强制更新之前已在本地集成。

如果传递新选项时未指定“ --force-with-lease”,或与“”一起指定,--force-with-lease=<refname>:<expect>则为“无操作”。


Hum*_*man 15

我想描述一个看似合理的案例,在该案例中,这--force-with-lease并不能避免您覆盖同事的工作。

一切都从鲍勃开始

在签出最新的主分支时执行以下操作:

# Creating a new branch called feature/one
$ git checkout -b feature/one

# Do some changes and git add ...
$ git commit

# Push for the first time
$ git push --set-upstream origin feature/one

# Checkout another branch to work on something else
Run Code Online (Sandbox Code Playgroud)

Bob 机器上的情况

...--F--G--H   <-- master (HEAD)
            \
             o--o   <-- feature/one
Run Code Online (Sandbox Code Playgroud)

爱丽丝继续

Alice 接手 feature/one 上的工作,并在 Bob 的工作之上提交内容并推送她的更改,同时一些不相关的拉取请求被合并到主分支。Alice 的工作树是什么样子的

...--F--G--H--I--J   <-- master (HEAD)
           \
            o--o--x--x   <-- feature/one
Run Code Online (Sandbox Code Playgroud)

鲍勃继续

Bob 的任务是在当前主分支上重新调整 Alice 的工作,并执行以下操作

  1. git pull而他在 master 分支上,基本上就是 agit fetch和 agit merge 这一步的后果稍后会很重要。

    Bob机器上的情况:

    ...--F--G--H--I--J   <-- master (HEAD)
                \
                 o--o   <-- feature/one
    
    Run Code Online (Sandbox Code Playgroud)
    ...--F--G--H--I--J   <-- origin/master (HEAD)
                \
                 o--o--x--x   <-- origin/feature/one
    
    Run Code Online (Sandbox Code Playgroud)

    Bob 的机器现在包含一个最新的遥控器,但 origin/feature/one 中的更改尚未合并到 feature/one。

  2. 鲍勃检查分支git checkout feature/one

  3. 鲍勃忘记做一个git pull
  4. Bob 在 master 上重新建立了他的本地分支git rebase -i origin/master

    bobs 机器上的情况如下所示:

    ...--F--G--H--I--J   <-- master (HEAD)
                      \
                       o--o   <-- feature/one
    
    Run Code Online (Sandbox Code Playgroud)
  5. Bob 认为他成功地重新调整了他的分支并强制推送到feature/oneorigin/feature/one因为 Bob 是一个好人,他推送了git push --force-with-lease origin feature/one并期望该选项 --force-with-lease将阻止他的推送操作,如果他要覆盖其他人的工作。 但这个选项不会拯救他,如果我正确理解 这篇博客文章--force-with-lease那么鲍勃机器上的 origin/feature/one 和实际的 origin/feature/one 之间没有区别,因此假设 Bob 的工作树不会覆盖 Bob 机器上的任何内容。如果强制推到它,则远程。缺乏差异的原因在于在不同分支上执行隐式git fetch作为早期(在本节的步骤 1 中)的一部分。git pull

    推送后,遥控器会是这样的

    ...--F--G--H--I--J   <-- master (HEAD)
                      \
                       o--o   <-- feature/one
    
    Run Code Online (Sandbox Code Playgroud)

    代替

    ...--F--G--H--I--J   <-- master (HEAD)
                      \
                       o--o--x--x   <-- feature/one
    
    Run Code Online (Sandbox Code Playgroud)

    这是上面链接的博客文章的相关部分:

    提取将从远程提取对象和引用,但如果没有匹配的合并,则不会更新工作树。这将使远程的工作副本看起来好像远程的工作副本是最新的,而不实际包含新工作,并欺骗--force-with-lease覆盖远程分支

  • 谢谢你提供的例子,我刚刚测试了这个,并且可以确认即使使用 --force-with-lease ,Alice 的提交 xx 也会丢失。 (3认同)

dan*_*1st 5

不安全

请参阅这篇 atlassian 博客文章,其中描述了git push --force-with-leasegit push -f. 然而,它部分地覆盖了遥控器,使其不安全。

但是 --force 有一个不太为人所知的兄弟,可以部分防止破坏性的强制更新;这是--force-with-lease。

不同之处在于,--force-with-lease如果远程包含本地存储库不知道的工作,则会进行额外的检查并中止。但它仍然会覆盖远程分支,导致与 相同的问题-f,只是如果其他人同时推送,它不会这样做。