【问题标题】:Git switching branches issue: cannot fetch remote branch changesGit切换分支问题:无法获取远程分支更改
【发布时间】:2021-12-12 06:44:33
【问题描述】:

我一直在使用 git,并且能够创建一个分支并推送源。我对基本的了解很少,但仍在学习。

今天我在一个名为 B 的分支上工作,并且并行,但有时我正在做一些调试分支文件夹 A 但没有在分支之间切换,只是处理文件并将它们保存到驱动器。

所以我想切换回分支A以将更改推送到git 所以我做到了

git checkout A

错误:以下未跟踪的工作树文件将被结帐覆盖: cc.py dd.py ....一些其他文件 不太明白为什么会出现此错误,因为我的分支是B,而错误下方的那些文件属于分支-A 文件夹。反正我做到了

git checkout -f A

切换到分支“A” 你的分支是最新的'origin/A'。

这怎么可能发生?我已经在本地更新了分支A 中的文件,但它说你是最新的??

然后我做了

git status

没有要提交的文件。一切都是最新的。所以我想如果我fetch这个分支的远程版本,它会识别分支的本地版本和远程版本之间的差异A

然后我做了

git remote update

Fetching origin
remote: Enumerating objects: 27, done.
remote: Counting objects: 100% (27/27), done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 14 (delta 11), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (14/14), 1.76 KiB | 39.00 KiB/s, done.

做过

git fetch origin A
  • 分支 A -> FETCH_HEAD

基本上无论我尝试什么,我都无法让更改后的文件状态在我的本地存储库分支 A 中显示为红色。所以我尝试从远程 fetch 获取 localremote 版本之间的差异A 分支。那也是失败的。

我真的很困惑为什么会发生这种情况,并且真的在寻求帮助来解决这个问题! 谢谢

What is the difference between 'git pull' and 'git fetch'?

【问题讨论】:

  • (注意:这不是答案,只是一般性建议:)不要以- 作为其名称的第一个字符来命名分支,这是个坏主意。这不是真正的问题,您可以始终将它们称为refs/heads/-A,例如避免以- 开头,但实际上,不要这样做,因为分支名称看起来像 Git 的一个选项,这会让生活变得悲惨命令。
  • @torek 正如你所提到的,-A 代表名称只是编造的名称。我编辑了 OP 以避免混淆。它不是 OP 中提出的实际问题。

标签: git github gitlab


【解决方案1】:

TL;DR

切换分支可能需要更改 Git 索引和工作树的内容。这可能会丢失您正在做的工作。你遇到过这样的情况。通常,您必须强制 Git 丢失工作(尽管旧的 git checkout 命令存在一些小问题,很容易破坏未保存的工作,在新的 git switch 中已修复)。

这里有很多要知道的。

您将许多概念混合在一起,当您使用 Git 时,您需要在脑海中保持独立。特别是,您似乎对 Git 的介绍很糟糕。一个好的开始:

  • Git 是关于提交

  • 提交包含文件,但 Git 与文件无关。 Git 是关于提交的。

  • 分支——或者更准确地说,分支names——帮助你和 Git find 提交,但 Git 也不是关于分支的。

所以 Git 基本上只是一个充满提交的大型数据库(以及其他支持对象,此外还有一些较小的数据库)。提交是 Git 的 raison d'être

众所周知,what someone tells you three times is true,? 所以接下来要学习的是什么是提交。这有点抽象:很难指着房间里的东西说那里,那是一个提交!,因为没有现实世界的类似物。但在 Git 中:

  • 每个提交都编号,具有一个看起来像随机垃圾的唯一编号。它实际上是一个密码校验和(让人联想到加密货币,这里实际上存在一种关系),用hexadecimal 表示,但我们可以把它看作是一个明显随机的垃圾字符串,没有人会记住。然而,对于一个特定的提交来说是唯一的:一旦一个数字被任何一个提交使用,任何地方的任何人都不能将它用于任何其他提交。1

    这就是两个不同的 Git(实现 Git 的两个软件,使用两个不同的存储库)如何判断它们是否都有一些提交。他们只是查看彼此的提交数字。如果数字相同,则提交相同。如果不是,则提交是不同的。所以从某种意义上说,数字提交,除了数字只是提交的散列,如果你没有数字,你需要得到整个提交(来自拥有它的人)。

  • 同时,每个提交存储两件事:

    • 每个提交都有一个每个文件的完整快照。更准确地说,每个提交都有它拥有的所有文件的完整快照。这听起来是多余的,但提交 a123456 可能有 10 个文件,而提交 b789abc 可能有 20 个文件,所以显然某些提交可能比另一个提交更多的文件。这样做的重点是要注意,只要您有提交,您就会拥有所有文件的完整快照,就像存档一样。

      提交内部的文件以特殊的 Git-only 形式存储。它们被压缩并且——更重要的是——重复数据删除。这可以防止存储库变得非常臃肿:大多数提交主要重用以前提交的文件,但是当他们这样做时,文件都被删除了重复数据,因此新提交几乎不占用任何空间。只有真正不同的文件需要进入;与以前相同的文件只是被重复使用。

    • 除了快照之外,每个提交都有一些元数据。元数据只是关于提交本身的信息。这包括诸如提交人的姓名之类的内容。它包括一些日期和时间戳:when 他们做出了提交。它包括一条日志消息,他们在其中说为什么他们做出了提交。

      对于 Git 本身至关重要,Git 在此元数据中添加了一个提交编号列表——“哈希 ID”或“对象 ID”(OID)——之前次提交。

大多数提交只存储一个哈希 ID,用于(单数)先前或 提交。这种形式提交到。这些链条向后工作,这是有充分理由的。


1这种完全唯一性的想法在实践中是正确的,但在理论上是不正确的,但只要它在实践中是正确的就可以了。为了使其在实践中发挥作用,这些数字需要尽可能大——或者很快,更大,而 Git 人员现在正在努力让它们变得更大。


每次提交的所有部分都是只读的

为了使提交编号(加密哈希 ID)起作用,Git 需要确保任何提交的任何部分都不能更改。事实上,你可以从 Git all-commits 数据库中取出一个提交,然后用它来更改内容或元数据并将其放回原处,但是当你这样做时,你只会得到一个 新的和不同的提交 em> 具有新的唯一哈希 ID。旧的提交保留在旧 ID 下的数据库中。

因此,提交是由两部分组成的东西——快照和元数据——它是只读的,或多或少是永久的。您真正使用 Git 所做的只是添加更多提交。您实际上无法取出任何东西,2 但很容易添加新的,因为这就是 Git 的初衷。


2但是,您可以停止使用提交,如果提交不仅未使用而且不可找到,Git最终会意识到这个提交是垃圾,并将丢弃它。因此,如果需要,这就是您摆脱提交的方法:您只需确保它们无法找到,然后 Git 最终——这需要一段时间!——将它们扔掉。不过,我们不会在这里详细介绍。


让我们多谈谈父母和反向链的事情

虽然这与您现在正在做的事情无关,但它确实很重要,所以让我们看看提交链是如何工作的。我们已经说过,大多数提交记录了一个较早提交的原始哈希 ID。我们还说过哈希 ID 又大又丑,对人类来说是不可能的(这是真的:e9e5ba39a78c8f5057262d49e261b42a8660d5b9 到底是什么意思?)。因此,假设我们有一个包含一些提交的小型存储库,但我们使用单个大写字母代替它们的真实哈希 ID,而不是这些提交。

我们将从一个只有 三个 提交的存储库开始,我们将其称为 ABCC 将是 最新 提交。让我们把它画进去:

      <-C

C 包含早期提交 B 的原始哈希 ID。我们喜欢将它们绘制为从提交中出来的箭头,并说C 指向 B。让我们现在也画B

  <-B <-C

当然B 有这些箭头之一,指向较早的提交A

A <-B <-C

这是我们完整的提交链。 A,作为第一个提交,没有指向任何更早的东西,因为它不能,所以链在这里停止。

为了添加一个新的提交,我们告诉 Git 用提交 C 做一些事情——我们稍后会更完整地描述这个——然后使用 @ 987654349@ 进行新的提交,然后将指向C

A <-B <-C <-D

现在我们的链中有 四个 提交,新提交 D 指向 C

除了这些向后的箭头,每个提交都有一个完整的快照。当我们创建D 时,我们大概更改了一些文件——同样,我们稍后会更详细地讨论这个问题——所以D 中的一些文件与C 中的文件不同.我们大概留下了一些文件。我们现在可以让 Git 向我们展示D 中的更改

为此,Git 将 both C D 提取到临时区域(在内存中)并检查包含的文件。当他们匹配时,它什么也没说。 Git 执行的重复数据删除使这个测试变得容易,Git 实际上可以完全跳过这些文件的提取。只有对于 不同 的文件,Git 实际上才需要提取它们。然后它比较它们,玩一种Spot the Difference 的游戏,并告诉我们这些更改的文件有什么不同。那是git diff,也是我们从git log -pgit show 看到的。

当我们在一次提交上运行 git show 时,Git:

  • 以某种格式打印元数据或其中的某些选定部分;和
  • 运行这种差异来查看这个提交的父级和这个提交之间有什么不同。

当我们运行git log,Git:

  • 从最后一次提交开始D
  • 向我们展示了该提交,如果我们使用-p,可能也带有git show 样式差异;那么
  • 向后移动一跳到上一个提交,C,然后重复。

只有当我们厌倦了查看git log 输出,或者 Git 到达第一个提交 (A) 时,此过程才会停止。

寻找提交

让我们再画几个提交。我将对提交之间的内部箭头变得懒惰:它们是每个提交的一部分,因此不能改变,所以我们知道它们总是指向后面。我将在这里用哈希 H 结束我的链:

...--F--G--H

一旦我们有 lot 的提交(超过此所暗示的 8 个左右),就很难确定哪个看起来随机的哈希 ID H 实际上。我们需要一种快速的方法来找到哈希,H

Git 对此的回答是使用分支名称。分支名称就是任何符合name restrictions 的旧名称。该名称包含 一个 哈希 ID,例如提交 H 的哈希 ID。

给定一个包含提交H 的哈希ID 的名称,我们说这个名称​​指向 H,并把它画进去:

...--G--H   <-- main

如果我们愿意,我们可以有多个名称指向提交H

...--G--H   <-- develop, main

我们现在需要一种方法来了解我们正在使用哪个名称。为此,Git 将一个非常特殊的名称 HEAD 附加到一个分支名称上,像这样全部大写。附有HEAD 的名称是当前分支,该分支名称指向的提交是当前提交。所以:

...--G--H   <-- develop, main (HEAD)

我们是on branch main,正如git status 所说,我们正在使用哈希ID 为H 的提交。如果我们运行:

git switch develop

作为一个 Git 命令,它告诉 Git 我们应该停止使用名称 main 并开始使用名称 develop

...--G--H   <-- develop (HEAD), main

当我们这样做时,我们从提交H 移动到...提交H。我们实际上并没有任何地方。这是一种特殊情况,Git 确保除了更改 HEAD 的附加位置之外什么都不做。

现在我们“开启”了分支develop,让我们进行 提交。我们不会过多地谈论如何我们现在这样做,但我们会回到那个,因为这是您当前问题的核心。

无论如何,我们将引入我们的new 提交I,它将指向现有的提交H。 Git 知道I 的父级应该是H 因为,当我们开始时,名称develop 选择提交H,因此H 是当前提交 在我们开始整个“make new commit”过程的时候。 最终结果是这样的:

          I   <-- develop (HEAD)
         /
...--G--H   <-- main

也就是说,name develop 现在选择提交 I,而不是提交 H。存储库中的其他分支名称没有移动:它们仍然选择之前所做的任何提交。但现在develop 表示提交I

如果我们再次提交,我们会得到:

          I--J   <-- develop (HEAD)
         /
...--G--H   <-- main

即名称develop 现在选择提交J

如果我们现在运行 git switch maingit checkout main——两者都做同样的事情——Git 将删除所有与 J 相关的文件(它们被安全地永久存储 J 中)并提取 H 附带的所有文件:

          I--J   <-- develop
         /
...--G--H   <-- main (HEAD)

我们现在是on branch main,我们又拥有来自H 的文件。如果我们愿意,我们现在可以创建另一个新的分支名称,例如 feature,然后进入 那个 分支:

          I--J   <-- develop
         /
...--G--H   <-- feature (HEAD), main

注意通过H 并包括H 的提交是如何在所有三个分支上进行的,而提交I-J 仅在develop 上。当我们进行新的提交时:

          I--J   <-- develop
         /
...--G--H   <-- main
         \
          K--L   <-- feature (HEAD)

当前分支名称向前移动,以适应新的提交,并且新的提交仅在当前分支上。我们可以通过移动分支名称来改变这一点:names 移动,即使提交本身是一成不变的。

提交是只读的,那么我们如何编辑文件呢?

我们现在来到您问题的核心部分。我们不——事实上,我们不能——直接处理提交,因为它们是这种奇怪的仅 Git 格式。我们必须让 Gitextract 提交。我们已经看到 git checkoutgit switch 可以做到这一点,但现在是时候全面了解一下了。

为了完成新工作,Git 为您提供了 Git 所谓的 工作树工作树。这是一个目录(或文件夹,如果您更喜欢该术语),其中包含您计算机的普通文件格式的普通文件。 这些文件不在 Git 中。其中一些来自Git,可以肯定的是:git checkoutgit switch 进程填写 你的工作树。但它通过这个过程做到了:

  • 首先,如果您签出了一些现有的提交,Git 需要删除所有来自该提交的文件。
  • 然后,由于您将 移动到 一些 other 提交,Git 现在需要 创建(新鲜)存储在 那个提交。

所以Git会根据两次提交的不同,删除旧文件并放入新文件。

但是你的工作树是一个普通的目录/文件夹。这意味着 可以在这里创建文件,或在此处更改文件的内容,而 Git 对此过程没有任何控制或影响。您创建的一些文件将是全新的:它们不在 Git 中,它们不是来自 Git,Git 从未见过它们。其他文件实际上可能在很久以前的某个旧提交中,但不是来自 this 提交。一些文件确实来自这个提交。

当您使用git status 时,Git 需要比较您的工作树中的内容与某些内容。现在这个过程变得有点复杂了,因为 Git 实际上并没有从你的工作树中的文件进行 new 提交。3 相反,Git 保留了另一个 所有文件的副本

请记住,已提交的文件(当前或 HEAD 提交中的文件)是只读的,并且采用 Git 化的、去重复的格式,只有 Git 本身可以读取。因此,Git 将这些文件提取为普通文件,为每个文件留下 两个 个副本:

  • 提交中的 Git-only 只读文件,并且
  • 工作树中的那个。

但实际上,Git 偷偷地在这两个副本之间插入了一个副本,这样每个文件就有三个 个副本:

  • HEAD 中有 Git 化的,无法更改;
  • 在中间位置有一个 Git 化的准备提交副本;和
  • 您的工作树中有一个可用副本。

因此,如果您有一些像 README.mdmain.py 这样的文件,实际上每个文件都有三个副本。中间那个在 Git 调用的地方,不同的地方是 index,或 staging area,或 cache。这个东西一共有三个名字,可能是因为index这个名字太差劲了,cache也不好。 staging area 这个词可能是最好的词,但我会在这里使用 index,因为它更短且无意义,有时无意义也不错。 ?

那么,我们的文件的三个副本是:

  HEAD        index       work-tree
---------    ---------    ---------
README.md    README.md    README.md
main.py      main.py      main.py

Git 的 index 中的文件是 Git 将 提交 的文件。因此,我想说的是,Git 的索引是您提议的下一次提交

当 Git 第一次提取提交时,Git both 它的索引 你的工作树。 in Git 索引中的文件是预压缩和预去重的。由于它们来自提交,它们都是自动重复的,因此不占用空间。4工作树中的那些确实占用空间,但你需要那些因为你必须让它们去 Git 化才能使用它们。

当您修改工作树中的文件时,不会发生任何其他事情:Git 的索引没有改变。提交本身当然没有改变:它实际上不能改变。但是索引中的文件也没有发生任何事情。

一旦您进行了一些更改并希望提交这些更改,您必须告诉 Git:嘿,Git,将旧版本的文件从索引中踢出。阅读我的工作树版本main.py,因为我改变了它!立即将其压缩为您的内部压缩格式! 您可以使用 git add main.py 进行此操作。 Git 读取并压缩文件,并检查结果是否重复。

如果结果重复,Git 会踢出当前的main.py 并使用新的重复。如果结果不是重复,保存压缩文件以便准备好提交,然后做同样的事情:踢出当前的main.py并放入在文件的现在去重(但第一次出现)副本中。所以不管怎样,索引现在已经更新并准备好了。

因此,索引随时准备提交。如果您修改某些现有文件,则必须git add:这会通过更新索引来压缩、消除重复和准备提交。如果你创建一个全新的文件,你必须git add:这会压缩、去重复和准备提交。通过更新 Git 的索引,您可以准备好提交的文件。

这也是您删除文件的方式。它保留在当前提交中,但如果你使用git rm,Git 将同时删除索引副本工作树副本:

git rm main.py

产生:

  HEAD        index       work-tree
---------    ---------    ---------
README.md    README.md    README.md
main.py

您所做的下一个提交不会有main.py


3这实际上很奇怪:大多数非 Git 版本控制系统确实使用您的工作树来保存提议的下一次提交。

4索引条目本身会占用一些空间,通常每个文件大约 100 个字节或略低于 100 个字节,用于保存文件名、内部 Git 哈希 ID 和其他使 Git 有用的东西快。


现在我们看看git commit 是如何工作的

当你运行git commit,Git:

  • 收集任何需要的元数据,例如来自git configuser.nameuser.email,以及进入新提交的日志消息;
  • 当前提交的哈希 ID 是新提交的父级;
  • Git 的 index 中的任何内容都是 snapshot,因此 Git 将索引冻结为新的快照;和
  • Git 写出快照和元数据,获取新提交的哈希 ID。

在您运行 git commit 之前,我们不知道哈希 ID 是什么,因为进入元数据的部分内容是当时的 当前日期和时间,而我们不知道'不知道什么时候你会做出那个提交。所以我们永远不知道任何 future 提交哈希 ID 会是什么。但我们确实知道,因为它们都是一成不变的,所有过去的提交哈希 ID 是什么。

所以现在 Git 可以写出 commit I:

          I
         /
...--G--H   <-- develop (HEAD), main

一旦 Git 将其写出并获得哈希 ID,Git 可以将该哈希 ID 填充到 分支名称 develop,因为这是附加 HEAD 的位置:

          I   <-- develop (HEAD)
         /
...--G--H   <-- main

这就是我们分支的成长方式。

索引,或暂存区,决定了下一次提交的内容。您的工作树允许您编辑文件,以便您可以git add 将它们放入 Git 的索引中。 checkout 或 switch 命令从索引中删除 当前提交的 文件,然后转到 chosen 提交,填写 Git 的索引和您的工作树,并选择哪个分支名称-and-commit 将成为 新的当前提交。这些文件从那个提交中输出并填写 Git 的索引和您的工作树,然后您就可以再次工作了。

但是,直到您真正运行 git commit,您的文件才 Git 中。一旦你运行git add,它们就在Git 的index 中,但这只是一个临时存储区域,将被下一个git checkoutgit switch 覆盖。真正拯救他们的是git commit 步骤。这也将新提交添加到 当前分支

介绍其他 Git 存储库

现在,除了上述所有内容之外,您还使用了git fetch。当至少有 两个 Git 存储库 时,您可以使用它。我们之前提到过,我们将使用两个存储库将两个 Git(Git 软件的两个实现)相互连接并让它们传输提交。一个 Git 可以通过显示哈希 ID 来判断另一个 Git 是否有提交:另一个 Git 在其所有提交的大数据库中那个提交,或者没有。如果缺少提交的 Git 说 我没有那个,给我,那么 发送 Git 必须打包该提交 - 以及任何所需的支持对象 - 并且将它们发送过来,现在 receiving Git 也有该提交。

我们在这里总是使用单向传输:我们运行git fetchget 来自其他 Git 的提交,或者运行 git push发送 提交 em> 其他一些 Git。这两个操作(获取和推送)与 Git 的对立一样接近,尽管这里存在某种根本的不匹配(我不会讨论,因为这已经很长了)。我们只谈fetch

当我们将我们的 Git 连接到其他 Git 时——让我们在这里使用 GitHub 的 Git 软件和存储库作为我们的示例,尽管使用正确的 Git 软件协议的任何东西都可以使用 git fetch,我们:

  1. 让另一个 Git 列出它的所有分支(和标签)名称以及与这些分支名称相关的提交哈希 ID(标签使事情变得更复杂,所以我们将在这里忽略它们)。

  2. 对于我们没有但感兴趣的每个提交哈希ID——我们可以在这里限制我们打扰的分支名称,但默认是全部 很有趣——我们要求他们请发送该提交!。他们现在有义务提供这些提交的 parent 提交。我们检查我们是否有 那些 提交,如果没有,也询问那些。这种情况一直持续到他们得到我们确实拥有的提交,或者完全用完提交。

  3. 这样,我们将从他们那里获得他们拥有的每一个我们没有的提交。然后,他们将这些与任何所需的支持内部对象一起打包,并将它们全部发送出去。现在我们有了他们所有的提交!

  4. 但还记得我们是如何find 在我们的存储库中使用branch 名称提交的吗?我们现在有一个问题。

假设我们的存储库中有这些提交:

...--G--H--I   <-- main (HEAD)

也就是说,我们只有一个分支名称,main。我们之前通过H 从他们那里获得提交,但后来我们自己提交了I

与此同时,当我们提交 I 时,他们提交了 J 并将其放在 他们的 main 上,所以 他们有:

...--G--H
         \
          J   <-- main (HEAD)

我用J 画了这个,因为当我们结合我们的提交和他们的提交时,我们最终得到:

...--G--H--I   <-- main (HEAD)
         \
          J

我们将附加什么 name 来提交 J 以便能够找到它? (请记住,它的真实名称是一些大而丑陋的随机哈希 ID。)他们正在使用名为main他们的 分支来找到它,但是如果我们移动 我们的分支main指向J,我们将失去我们自己的I

所以我们不会更新我们的任何分支名称。相反,我们的 Git 将为它们的每个 branch 名称创建或更新一个 remote-tracking 名称

...--G--H--I   <-- main (HEAD)
         \
          J   <-- origin/main

我们的远程跟踪名称显示为git branch -r,或git branch -a(显示我们自己的分支名称​​和我们的远程跟踪名称)。远程跟踪名称只是我们的 Git 记住他们的分支名称的方式,我们的 Git 通过在他们的分支名称前面粘贴 origin/ 来弥补它。5

现在我们有他们的提交我们的提交,加上远程跟踪名称,如果他们不完全重叠我们的提交,可以帮助我们找到他们的提交,现在我们 他们的提交可以做一些事情。我们所做的“某事”取决于我们想要完成的事情,而这里的事情实际上开始变得复杂——所以我会在这里停下来。


5从技术上讲,我们的远程跟踪名称位于单独的 namespace 中,因此即使我们做一些疯狂的事情,例如创建一个名为 origin/hello 的(本地)分支,Git 将保持这些直。但是不要这样做:即使使用 Git 为不同名称着色的技巧,您也可能会感到困惑。


那么您的更改发生了什么?

让我们再看看这部分:

$ git checkout A
error: The following untracked working tree files would be overwritten by checkout:
 cc.py dd.py ....

这些是您创建的文件,并非来自之前的提交。它们在您的工作树中,但不在 Git 中。 (“未跟踪”的意思是“甚至不在 Git 的索引中”。)

checkout 命令给了你这个错误,让你可以在 Git 中(通过添加和提交文件)或其他地方保存文件。但你没有提到这样做:

$ git checkout -f A

-f,或--force,这里的标志表示继续,覆盖这些文件。所以你创建的文件 消失了:分支名称A 选择了一个包含这些文件的提交,所以它们从提交中出来,进入 Git 的索引,并被扩展到你的工作树中。

以前的工作树文件从未在 Git 中,因此 Git 无法检索它们。如果您有其他方法来检索它们 - 例如,如果您的编辑器保存备份 - 使用它。如果没有,你可能会倒霉。

【讨论】:

  • 奥斯卡也去了!!解决我的问题的部分在哪里,我阅读了整个答案,但在其中找不到解决方案。基本上我什么都没做。我刚刚将分支从B 切换到A,仅此而已。我什至无法提交我在分支A 中所做的更改,因为 git 突然说出了your branch is up the date。怎么会这样?
  • 您使用git checkout -f 放弃您的所有更改。他们走了。它们在工作树中,但你告诉 Git 覆盖它们。
  • 好的,就是这样:) 请继续。所以git switch 是我下次应该使用的新命令,它会捕获我在分支A 中的提交离开的位置?
  • git switch 命令很像这里的git checkout:如果它说它会破坏未保存的工作,您可能希望先将工作保存在某个地方。如果您愿意丢弃未保存的工作,这里的--force 操作是一样的。 git switchgit checkout 的主要区别在于git checkout 有多种操作模式,而git switch 则很少。其他git checkout 模式被复制到一个单独的命令git restore
猜你喜欢
  • 2014-04-27
  • 2020-12-27
  • 2012-03-21
  • 1970-01-01
  • 2011-11-25
  • 2015-10-19
相关资源
最近更新 更多