Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

处理分散的 git 分支

Posted on 2024-02-02

你好!我看到人们在 Git 中遇到的最常见问题之一是本地分支(如main )和远程分支(也可能称为main )出现分歧。

有两件事使这种情况变得困难:

  • 如果你不习惯解释 git 的错误消息,那么即使意识到你的main已经与远程main发生了分歧,这也是不平凡的(git 通常只会给你一个令人生畏但通用的错误消息,比如! [rejected] main -> main (non-fast-forward) error: failed to push some refs to 'github.com:jvns/int-exposed' )
  • 一旦你意识到你的分支已经偏离了远程main ,就没有单一明确的方法来处理它(你需要做什么取决于情况和你的 git 工作流程)

那么,让我们来谈谈 a) 当您处于本地分支和远程分支出现分歧的情况时如何识别以及 b) 您可以采取什么措施!这是一个快速目录:

  • “分歧”是什么意思?
  • 识别分支何时分叉
    • 方式一:git状态
    • 方式二:git推送
    • 方式三:git pull
  • 没有一个解决方案
    • 解决方案1.1:git pull –rebase
    • 解决方案1.2:git pull –no-rebase
    • 解决方案2.1:git push –force
    • 解决方案 2.2:git push –force-with-lease
    • 解决方案3: git reset –hard origin/main

让我们从两个分支“分叉”意味着什么开始。

“分歧”是什么意思?

如果您有本地main和远程main ,则有 4 种基本配置:

1:最新的。本地和远程main分支位于完全相同的位置。像这样的东西:

 a - b - c - d ^ LOCAL ^ REMOTE

2:本地落后

在这里你可能想要git pull 。像这样的东西:

 a - b - c - d - e ^ LOCAL ^ REMOTE

3:遥控器在后面

在这里你可能想要git push 。像这样的东西:

 a - b - c - d - e ^ REMOTE ^ LOCAL

4:他们分歧了:(

这就是我们在这篇博文中讨论的情况。它看起来像这样:

 a - b - c - d - e \ ^ LOCAL -- f ^ REMOTE

没有一种方法可以解决这个问题(您想要如何处理它取决于具体情况和您的 git 工作流程!),但让我们讨论一下如何认识到您处于这种情况以及如何解决它的一些选项。

识别分支何时分叉

有 3 种主要方法可以判断您的分支已出现分歧。

方式一: git status

最简单的方法是运行git fetch然后运行git status 。您会收到类似这样的消息:

 $ git fetch $ git status On branch main Your branch and 'origin/main' have diverged, <-- here's the relevant line! and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours)

方式二: git push

当我运行git push时,有时会收到如下错误:

 $ git push To github.com:jvns/int-exposed ! [rejected] main -> main (non-fast-forward) error: failed to push some refs to 'github.com:jvns/int-exposed' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (eg hint: 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.

这并不总是意味着我的本地main和远程main已经分歧(这可能只是意味着我的main落后了),但对我来说这通常意味着这一点。因此,如果发生这种情况,我可能会运行git fetch和git status来检查。

方式三: git pull

如果我在分支出现分歧时git pull ,我会收到以下错误消息:

 $ git pull hint: You have divergent branches and need to specify how to reconcile them. hint: You can do so by running one of the following commands sometime before hint: your next pull: hint: hint: git config pull.rebase false # merge hint: git config pull.rebase true # rebase hint: git config pull.ff only # fast-forward only hint: hint: You can replace "git config" with "git config --global" to set a default hint: preference for all repositories. You can also pass --rebase, --no-rebase, hint: or --ff-only on the command line to override the configured default per hint: invocation. fatal: Need to specify how to reconcile divergent branches.

这个问题非常清楚(“你有不同的分支”)。

尽管当您的分支出现分歧时, git pull并不总是会输出此错误消息:这取决于您如何配置 git。我知道的其他三个选项是:

  1. 如果你设置git config pull.rebase false ,它会自动开始合并远程main
  2. 如果你设置git config pull.rebase true ,它会自动开始重新定位到远程main
  3. 如果git config pull.ff only ,它将退出并显示错误fatal: Not possible to fast-forward, aborting.

既然我们已经讨论了一些方法来识别您所处的情况,即本地分支与远程分支存在分歧,那么让我们谈谈您可以采取哪些措施。

没有一个解决方案

没有“最佳”方法来解决分歧的分支 – 这实际上取决于您的 git 工作流程以及发生这种情况的原因。

我根据具体情况使用3种主要解决方案:

  1. 我想将两组更改保留在main上。为此,我将运行git pull --rebase 。
  2. 远程更改没有用,我想覆盖它们。为此,我将运行git push --force
  3. 本地的修改没用,我想覆盖它们。为此,我将运行git reset --hard origin/main

以下是有关所有这 3 个解决方案的更多详细信息。

解决方案1.1: git pull --rebase

当我想保留两组更改时,我就是这样做的。它将main重新设置为远程main分支。我主要在存储库中使用它,我在main分支上完成所有工作。

您可以配置git config pull.rebase true ,每次都会自动执行此操作,但我不这样做,因为有时我实际上想使用解决方案 2 或 3 (用远程覆盖我的本地更改,或相反)。我宁愿被警告“嘿,这些分支已经分歧,你想如何处理它?”并自行决定是否要重新设置基准。

解决方案1.2: git pull --no-rebase

这将启动local和远程main之间的合并。在这里你需要:

  1. 运行git pull --no-rebase 。这将启动合并并(如果成功)打开一个文本编辑器,以便您可以确认是否要提交合并
  2. 将文件保存在文本编辑器中。

对此我没有太多可说的,因为我从来没有这样做过。我总是使用 rebase 来代替。不过,这是个人的工作流程选择,很多人都有非常合理的理由避免 rebase 。

解决方案2.1: git push --force

有时我知道远程main上的工作实际上是无用的,我只想用本地main上的任何内容覆盖它。

我经常在私人存储库上这样做,我是唯一的提交者,例如我可能:

  • git push一些提交
  • 迟来的决定我想改变最近的提交
  • 进行更改并运行git commit --amend
  • 运行git push --force

当然,如果存储库有许多不同的提交者,以这种方式强制推送可能会导致很多问题。在共享存储库上,我通常会启用github 分支保护,这样就不可能强制推送。

解决方案 2.2: git push --force-with-lease

我仍然从未真正使用过git push --force-with-lease ,但我看到很多人推荐它作为git push --force的替代品,以确保自上次以来没有其他人更改过分支您推送或获取的时间,这样您就不会意外地破坏它们的更改。似乎是一个不错的选择。

解决方案3: git reset --hard origin/main

您可以将其用作git push --force的反向操作(因为没有git pull --force )。当我知道我的本地工作不应该在那里并且我想扔掉它并用远程分支上的任何内容替换它时,我就会这样做。

例如,如果我不小心对实际上应该在新分支上的main进行了提交,我可能会这样做。解决这个问题看起来像这样:

 # 1. put the commit on `new-branch` git checkout -b new-branch # 2. go back to the `main` branch I messed up git checkout main # 3. make sure that my `origin/main` is up to date git fetch # 4. double check to make sure I don't have any uncomitted # work because `git reset --hard` will blow it away git status # 5. force my local branch to match the remote `main` # NOTE: replace `origin/main` with the actual name of the # remote/branch, you can get this from `git status`. git reset --hard origin/main

与往常一样, git reset --hard是一个危险的操作,您可能会永久丢失未提交的工作。我总是先运行git status以确保没有任何未提交的更改。

使用git reset --hard的一些替代方法:

  • 查看其他一些分支并运行git branch -f main origin/main 。
  • 查看其他一些分支并运行git fetch origin main:main --force

就这样!

我从来没有真正想过如果你不习惯阅读git push和git pull错误消息,它们会多么令人困惑。

原文: https://jvns.ca/blog/2024/02/01/dealing-with-diverged-git-branches/

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Bits about Money
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Christopher Butler
  • Colin Percival
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Dustin Curtis
  • Elad Gil
  • Ellie Huxtable
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • Henrique Dias
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Liz Danzico
  • Lou Plummer
  • Luke Wroblewski
  • Matt Baer
  • Matt Stoller
  • Matthias Endler
  • Mert Bulan
  • Mostly metrics
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • Sam Rose
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • thesephist
  • Thinking Deep & Wide
  • Tim Kellogg
  • Understanding AI
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme