我刚接触Git,还在尝试了解分支的工作方式。根据文档,git checkout
:
更新工作树中的文件以匹配索引或指定树中的版本。如果>没有给出路径,git checkout也会更新HEAD以将指定的分支设置为>当前分支。
据我所知,我工作的目录中的文件(我在其中执行git init
的文件)应该根据我所在的分支而改变。我很困惑,因为当我在分支之间切换时不会发生这种情况。我切换分支之前正在进行的编辑存在于我切换到的分支中。我做错了什么吗?或者git checkout
不这样工作,我只是误解了文件。
3条答案
按热度按时间a14dhokn1#
Git 2.23也承认了这一点。
Git 2.23(2019年第三季度)将用两个新命令替换
git checkout
:git switch
个git restore
(illustrated here)的值请参见commit 97ed685、commit d16dc42、commit bcba406(2019年6月20日),commit 4e43b7f、commit 1235875、commit 80f537f、commit fc991b4、commit 75f4c7c、commit 4df3ec6、commit 2f0896e、commit a5e5f39、commit 3a733ce、commit e3ddd3b、commit 183fb44、commit 4058199、commit a6cfb9b、commit be8ed50、commit c9c935f、commit 46e91b6(2019年4月25日)和commit 328c6cb(2019年3月29日)的最后一次给药。
(由Junio C Hamano --
gitster
--合并至commit f496b06,2019年7月9日)checkout
:将其一部分拆分为新命令“switch
””
git checkout
“执行的操作太多,会给许多用户带来困惑(有时甚至会让老用户感到困惑)。为了解决这个问题,这个命令将被拆分成两个新的命令:switch和restore。好的旧命令“
git checkout
“仍然存在,直到所有(或大多数用户)厌倦它。还有:
switch:如果某些操作正在进行,则拒绝
除非你知道自己在做什么,否则换到另一个分支去做某件事,然后又换回来可能会让你感到困惑。更糟糕的是,你甚至可能忘记自己正在做某件事。当你意识到自己已经做了大量的工作时,再回去会变得更难。
考虑了一个新选项
--ignore-in-progress
,但由于不清楚会发生什么,因此放弃了该选项。有时候你可以换掉,安全地回来,继续手术,有时候不行。
而
git-checkout
的行为是自动清除合并/还原/cherry-pick,这使得它更令人困惑。See this discussion的一个或多个。
我们可能会在将来重新考虑并添加此选项。
但现在要谨慎行事,不要允许它(你甚至不能跳过
--force
的检查)。建议用户自己取消操作(希望他们考虑到后果,而不是盲目地键入命令),或者创建一个单独的工作树,而不是切换。
第三个选项是很好的老“
git checkout
“,但它没有提到。请参阅
git switch
man page说明
切换到指定的分支。
更新工作树和索引以匹配分支。
所有新提交都将添加到此分支的尖端。
或者,可以使用
-c
、-C
从同名的远程分支自动创建新分支(请参见--guess
),或者使用--detach
从任何分支中分离工作树,沿着进行切换。切换分支不需要干净的索引和工作树(即,与
HEAD
相比没有差异)。但是,如果操作导致本地更改丢失,则会中止该操作,除非
--discard-changes
或--merge
另有说明。示例
下面的命令切换到“
main
“分支:字符串
在错误的分支中工作后,切换到正确的分支将使用以下命令完成:
型
但是,在您本地修改的文件中,“错误”分支和正确的“
mytopic
“分支可能不同,在这种情况下,上述开关将失败,如下所示:型
您可以为命令给予
-m
标志,该命令将尝试三向合并:型
在这个三向合并之后,本地修改 * 没有 * 注册在索引文件中,因此
git diff
将显示自新分支的尖端以来所做的更改。要在切换到
mytopic
(即“main
“分支)之前切换回上一个分支,请执行以下操作:型
您可以从任何提交中生成一个新分支。
例如,切换到“
HEAD~3
“并创建分支“fixup
“:型
如果要从同名的远程分支启动新分支,请执行以下操作:
型
要 checkout 提交
HEAD~3
以进行临时检查或试验,而不创建新分支,请执行以下操作:型
如果你所做的事情值得保留,你可以给它起一个新名字(不用换掉):
型
请注意错误消息“
git switch
“提到了创建新分支的选项,显示了“-b/-B
“选项,而“-c/-C
“选项应该在其中,这已在Git 2.27(Q2 2020)中得到纠正。参见Denton Liu (
Denton-L
)的commit 7c16ef7(2020年4月30日)。(2020年5月8日,由Junio C Hamano --
gitster
--合并于commit f4675f3)switch
:修复与-c和-C相关的错误和注解报告人:Robert Simpson
签核人:丹顿Liu
审核人:Taylor Blau
在d787d311db(“
checkout
:split part of it to new command 'switch'”,2019-03-29,Git v2.23.0-rc 0--merge在batch #4中列出)中,通过提取checkout_main()
中cmd_checkout()
的公共功能创建了git switch
命令。然而,在b7b5fce270(“
switch
:-b
和-B
的更好的名称“,2019-03-29,Git v2.23.0-rc 0--merge在batch #4中列出)中,”switch
“的分支创建选项和强制创建选项分别更改为-c
和-C
。因此,以前引用
-b
和-B
的错误消息和注解对于git switch
无效。对于引用
-b
和-B
的错误消息,请改用格式字符串,以便在调用git switch
时可以打印-c
和-C
。ioekq8ef2#
Git有一个普遍的问题,就是在一个命令中塞进八到十个不同的东西。注意:Git 2.23将其中一些拆分出来--这是有帮助的,当然,也是一个非常大的变化。(* Git 2.23应该被称为Git 3.0吗?Git 2.0改变了
git add
的行为,在我看来这在程度上是相似的。*)参见VonC's answer。git checkout
* 可以 * 更新工作树,而且通常会这样做。它可以改变
HEAD
指向的位置,有时会,有时不会。它可以覆盖你对文件所做的工作,以防你想重置文件并撤消你的工作。或者它可以拒绝覆盖你对文件所做的工作,在改变
HEAD
或不改变HEAD
时保持不变。关于这一切的事情是,虽然它非常难以描述,但实际上它都是有意义的,过了一段时间,你习惯了这一点,发现一个命令在大多数时候都能做到你想做的事情。(当然,“大多数时候”可能是一个问题.)
无论如何,你看到的特定行为是一个故意的特性。假设你从分支
main
开始,就像大多数仓库一样:字符串
此时,您可能会编辑一些文件,进行一些工作,然后才意识到:“天哪!我本来想在分支
develop
上做这个!“1Git允许您在这一点上切换到(或创建)分支
develop
,* 保留您的修改 *,只有一个条件:切换到develop
并不需要清除它们。假设您修改了文件f1
并创建了一个新的f2
,现在您希望创建并 checkout 本地分支develop
,该分支应该从,并自动“跟踪”,2origin/develop
:型
(in非常旧的git版本,你必须拼写这个
git checkout -b develop --track origin/develop
)。假设文件
f1
在分支main
和分支develop
的顶端是相同的。3这对git来说意味着它可以执行这个 checkout ,因为它不需要修改文件f1
,所以它可以保留对f1
的现有更改。如果文件
f2
在两次提交中 * 也 * 相同,或者(如本例中所示)不存在,则不会删除任何文件,git checkout
将创建新的本地分支develop
,根据需要修改工作树以匹配origin/develop
-这不包括修改f1
,也不包括删除f2
,所以你迄今为止所做的工作仍然完好无损。这允许您将新更改提交到本地
develop
。(If如果你遇到Git * 确实 * 必须撤销你的更改,但仍然想将它们“移动”到另一个分支,通常的技巧是使用
git stash
脚本。这听起来很简单,git stash
通常使用起来很简单,但它实际上是一个相当复杂的小野兽。不过,不要担心,直到你需要它。)1这种情况经常发生在我身上。很多时候我想创建一个新的非跟踪分支,这比切换到现有的分支要简单一些,但原则仍然适用。
2这种自动跟踪允许您更轻松地引入其他人所做的更改:一旦Git使用
git fetch
拾取它们,Git将通知您其他人的更改,并允许您使用git merge
或git rebase
将您的更改与他们的更改合并合并,而无需大量额外的探查来确定谁的更改在哪里。3因为你是Git新手,所以你应该暂时忽略一些概念,比如区分“分支的顶端”,这是一个特定的提交,“分支”,这实际上是模棱两可的--有分支 * 标签 *,然后还有由提交树形成的分支 * 结构 *。主要需要注意的是,Git仓库中有一个特殊的文件,名为
HEAD
,在这个特殊的文件中,git写入字符串ref: refs/heads/main
或ref: refs/heads/develop
,以跟踪您在哪个分支上。因此,一旦git checkout X
切换到分支X
,它就会将ref: refs/heads/X
写入HEAD
。与此同时,仓库中的另一组特殊文件告诉Git,分支
main
引用了一个像c06f8d11b75e28328cdc809397eddd768ebeb533
这样的大而丑陋的SHA-1。这是分支main
的“提示”。当你在main
上进行新的提交时,Git会创建新的提交“旧的提示”,然后将新的SHA-1写入分支文件,因此main
现在是新提交者。精确的细节并不重要,因为 new 提交只是推进了分支提示。
anhgbhbe3#
当您创建一个分支时,该分支将自动获取您创建此新分支时所在的分支的文件。
假设你在
main
分支中,你想创建一个develop
分支。所有这些看起来应该是这样的:字符串
然后你不会看到
text.txt
,因为你在main
中。