【问题标题】:Force "git push" to overwrite remote files强制“git push”覆盖远程文件
【发布时间】:2014-09-06 05:54:51
【问题描述】:

我想推送我的本地文件,并将它们放在远程仓库中,而不必处理合并冲突。我只是希望我的本地版本优先于远程版本。

如何使用 Git 做到这一点?

【问题讨论】:

  • git push origin --force 不适合你吗?
  • 不清楚您是否只想覆盖 .git 文件或相关的工作副本。如果它是 git 存储库,那么 git push 就是答案。如果要更新远程工作副本,则必须使用 post-receive 挂钩
  • @Mike 出于某种原因对我有用...想知道 OP 发生了什么
  • 强制推送不起作用的一个可能原因是,它可能已在远程仓库中被明确禁用(以确保不会因愚蠢和/或恶意贡献者而丢失):使用config receive.denyNonFastforwards找出答案。

标签: git git-push


【解决方案1】:

您应该能够使用

来强制对远程仓库进行本地修订
git push -f <remote> <branch>

(例如git push -f origin master)。离开&lt;remote&gt;&lt;branch&gt; 将强制推送所有已设置--set-upstream 的本地分支。

请注意,如果其他人共享此存储库,他们的修订历史将与新的冲突。如果他们在更改点之后有任何本地提交,他们将变得无效。

更新:我想我会添加一个旁注。如果您正在创建其他人将查看的更改,那么创建一个包含这些更改的分支并定期 rebase 以使它们与主开发分支保持同步并不少见。只需让其他开发人员知道这会定期发生,这样他们就会知道会发生什么。

更新 2:由于观看者的数量不断增加,我想补充一些额外信息,说明当您的 upstream 确实遇到强制推送时该怎么办。

假设我已经克隆了你的 repo 并添加了一些提交,如下所示:

D----E话题 / A----B----C开发

但后来development 分支被rebase 击中,这将导致我在运行git pull 时收到类似这样的错误:

拆包对象:100% (3/3),完成。 来自 * 分支开发 -> FETCH_HEAD 自动合并 CONFLICT(内容):合并 中的冲突 自动合并失败;修复冲突,然后提交结果。

在这里我可以解决冲突和commit,但这会给我留下一个非常丑陋的提交历史:

C----D----E----F话题 // A----B-------------C'发展

使用git pull --force 可能看起来很诱人,但要小心,因为这会让你陷入搁浅的提交:

D----E话题 A----B----C'发展

所以最好的选择可能是做一个git pull --rebase。这将要求我像以前一样解决任何冲突,但对于每个步骤而不是提交,我将使用git rebase --continue。最后提交历史看起来会更好:

D'---E'主题 / A----B----C'发展

更新 3: 您还可以使用 --force-with-lease 选项作为“更安全”的力量 推,as mentioned by Cupcake in his answer

使用“租约”强制推送允许强制推送失败,如果有 是您没想到的遥控器上的新提交(从技术上讲,如果 您还没有将它们提取到您的远程跟踪分支中), 如果您不想不小心覆盖别人的 你甚至还不知道的提交,而你只是想 覆盖你自己的:

git push <remote> <branch> --force-with-lease

您可以通过以下方式了解有关如何使用--force-with-lease 的更多详细信息 阅读以下任何内容:

【讨论】:

  • 由于这是选择的答案,我将在这里评论。自己工作时使用武力不是问题。例如,我的云主机从它自己的 git 开始。如果我在本地工作并构建一个项目,并且我想将它放在我的云主机(OpenShift)上,我有两个独立的 git 项目。我的本地和我的 OpenShift 之一。我可以随心所欲地获取本地信息,但现在想在我的 OpenShift 上预览它。然后,您第一次使用 -f 标志推送到 OpenShift。本质上是把你的本地 git 放到 OpenShift 上。
  • 你也可以git push -f,只要你要推送到的远程分支是你最近推送到的分支。
【解决方案2】:

你想强制推送

您基本上想要做的是强制推送您的本地分支,以覆盖远程分支。

如果您想更详细地了解以下每个命令,请参阅下面的详细信息部分。使用 Git 强制推送基本上有 4 种不同的选项:

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

如果您想对每个命令进行更详细的说明,请参阅下面我的长答案部分。

警告:强制推送将用您正在推送的分支的状态覆盖远程分支。在使用它之前确保这是你真正想要做的,否则你可能会覆盖你真正想要保留的提交。

强制推送详情

指定远程和分支

您可以完全指定特定的分支和远程。 -f 标志是 --force 的短版本

git push <remote> <branch> --force
git push <remote> <branch> -f

省略分支

当分支到推送分支被省略时,Git 会根据你的配置设置来计算它。在 2.0 之后的 Git 版本中,新的 repo 将具有默认设置来推送当前签出的分支:

git push <remote> --force

在 2.0 之前,新的 repos 将具有默认设置来推送多个本地分支。有问题的设置是remote.&lt;remote&gt;.pushpush.default 设置(见下文)。

省略远程和分支

当远程和分支都被省略时,git push --force 的行为由您的 push.default Git 配置设置决定:

git push --force
  • 从 Git 2.0 开始,默认设置 simple 基本上只会将您当前的分支推送到其上游远程对应部分。远程由分支的branch.&lt;remote&gt;.remote 设置确定,否则默认为原始存储库。

  • 在 Git 2.0 版之前,默认设置 matching 基本上只是将所有本地分支推送到远程上同名的分支(默认为 origin)。

您可以通过阅读git help configan online version of the git-config(1) Manual Page 了解更多push.default 设置。

使用--force-with-lease 强制推送更安全

使用“租约”强制推送允许强制推送失败,如果遥控器上有您没有预料到的新提交(从技术上讲,如果您还没有将它们提取到远程跟踪分支中),这如果您不想意外覆盖您甚至还不知道的其他人的提交,而您只想覆盖自己的提交,这很有用:

git push <remote> <branch> --force-with-lease

您可以通过阅读以下任何内容了解有关如何使用--force-with-lease 的更多详细信息:

【讨论】:

  • 你是对的,但这应该只在例外情况下使用。
  • @ScottBerrevoets "我宁愿推送我拥有的东西,让它远程覆盖而不是集成。" 我给了 OP 正是他所要求的。
  • 我知道,但 OP 可能不知道这样做的后果。你从技术上回答了这个问题,但我认为不这样做的警告并不过分。
  • @ScottBerrevoets 我正在尝试让版主将我的答案合并到规范中,因为我提到了新的--force-with-lease 选项;)
【解决方案3】:

另一个选择(避免任何可能对其他贡献者造成问题的强制推送)是:

  • 将您的新提交放在专用分支中
  • origin/master 上重置您的master
  • 将您的专用分支合并到master,始终保留来自专用分支的提交(这意味着在master 之上创建新修订版,这将反映您的专用分支)。
    有关模拟git merge --strategy=theirs 的策略,请参阅“git command for making one branch like another”。

这样,您可以将 master 推送到远程,而无需强制执行任何操作。

【讨论】:

  • 结果与“push -force”有何不同?
  • @alexkovelsky 任何强制推送都会重写历史记录,迫使 repo 的其他用户重置他们自己的本地 repo 以匹配新推送的提交。这种方法只会创建新的提交,不需要强制推送。
  • 我建议您在答案中添加一个标题:“您不想强制推送”:)
  • @alexkovelsky 好点。我已经相应地编辑了答案。
【解决方案4】:

为我工作:

git push --set-upstream origin master -f

【讨论】:

    【解决方案5】:

    git push -f 有点破坏性,因为它会重置团队中其他任何人所做的任何远程更改。更安全的选择是 {git push --force-with-lease}。

    {--force-with-lease} 所做的是拒绝更新分支,除非它是我们期望的状态;即没有人更新上游的分支。在实践中,这是通过检查上游 ref 是否符合我们的预期来工作的,因为 ref 是散列,并将父链隐式编码为它们的值。 您可以确切地告诉 {--force-with-lease} 要检查的内容,但默认情况下会检查当前的远程参考。这在实践中意味着当 Alice 更新她的分支并将其推送到远程存储库时,分支的 ref 指向头将被更新。现在,除非 Bob 从远程进行拉取操作,否则他对远程的本地引用将过期。当他使用 {--force-with-lease} 进行推送时,git 将根据新远程检查本地 ref 并拒绝强制推送。 {--force-with-lease} 只有在没有其他人在此期间将更改推送到远程时才有效地允许您强制推送。系上安全带是 {--force}。

    【讨论】:

      【解决方案6】:

      使用 tortoisegit 的简单步骤

      GIT 提供本地文件提交并推送到 git 存储库。

      步骤:

      1) 存储更改 存储名称

      2) 拉动

      3) 存储弹出

      4) 提交 1 个或多个文件并给出提交更改描述集作者和日期

      5)

      【讨论】:

        猜你喜欢
        • 2011-10-06
        • 1970-01-01
        • 2013-05-12
        • 2014-03-13
        • 2017-12-30
        相关资源
        最近更新 更多