检查出不同的分支后,为什么仍然存在未分级的更改?

时间:2014-09-19 17:28:00

标签: git git-checkout

我观察的内容与我对git checkout命令的了解不一致。在master以外的分支上,我对跟踪文件进行了一些修改;没有暂存和提交这些更改,我运行

git checkout master

Git在没有击打眼睑的情况下顺从;但更令人惊讶的是,我在该分支上所做的所有修改仍然存在!以下是复制情况的示例:

mkdir myrepo
cd myrepo
git init
touch README # create a new file
git add .
git commit -m "initial commit"
git checkout -b new-branch
echo "foo" >> README
git checkout master  

在此阶段,我工作树中的README文件包含foo行,即使我在另一个分支(new-branch)上添加了该行。我希望README为空,就像master提示中记录的版本一样。在查看foo之后,为什么master行仍然存在?

2 个答案:

答案 0 :(得分:5)

乍一看,你的问题似乎很无趣,但它让我意识到git checkout并不像看起来那么简单。谢谢你问:)

据我了解,您的问题是:为什么在检出foo后,未提交的更改(即添加的master行)仍然存在于工作树中?如果您查找git-checkout手册页,您将找到以下说明:

git checkout <branch>

    To prepare for working on <branch>, switch to it by updating the
    index and the files in the working tree, and by pointing HEAD at
    the branch. Local modifications to the files in the working tree
    are kept, so that they can be committed to the <branch>.

然而,这个描述似乎与你的例子中发生的事情相矛盾。你并不是第一个被它迷惑的人;见this discussion。在其中,Git的维护者Junio Hamano澄清了git checkout <commit-ish>在存在局部修改时的作用:

  

原则是我们允许您查看不同的分支   当您对工作树和/或索引进行本地更改时,   只要我们可以使索引和工作树假装好像   从干净的状态开始,你达到了本地修改状态   您正在检查的分支机构。


Junio Hamano的回应

发生的事情对我来说仍然不清楚,所以我进行了一些实验来解决问题,这是我对Junio Hamano回复的解释。首先,让我介绍一些术语:让

  • Cs表示源提交,即HEAD在结账操作之前指向的提交,
  • 表示暂存区域的状态,
  • Ws表示工作树的状态,
  • Ct表示目标提交,即我们尝试签出的提交。

我的理解是,在为每个跟踪的文件调用时,git checkout会获得以下差异,

  • diff(Cs,Is)(您可以在git diff --staged的输出中看到),
  • diff(Cs,Ws)(你可以在git diff的输出中看到),

并检查这些更改是否完全适用于目标提交,Ct。如果存在任何冲突,则中止结账操作。否则,HEAD移动到Ct,并保留暂存区域(Is)和工作树(Ws)的状态。

应用于您的示例

git checkout master之前

在行

之后
git commit -m "initial commit"
在您的示例中,您的仓库看起来像这样:

enter image description here

提交,暂存区域和工作树旁边的页面在相应的三个&#34; Git区域&#34;中表示README文件的内容。

&#34;在&#34; git checkout master

然后你运行

git checkout master

所以,假设我对Junio的anwer的解释是正确的,这里会发生什么?

因为当前分支new-branch和要签出的分支master都指向同一个提交A,所以Cs和Ct(使用我的术语)都对应于A。在那种情况下,当然,diff(Cs,Is)和diff(Cs,Ws)干净地适用于Ct;这里没有冲突。

因此,执行结账操作:

  • HEAD指向master
  • 保留暂存区域的状态,
  • 保留工作树的状态。

git checkout master

之后

由于在签出master时没有出现混淆,因此保留了对工作树中README的本地修改,以便可以将它们提交到master分支。

enter image description here

答案 1 :(得分:3)

在进行更改之前(使用git add),它只存在于工作目录中 - 它不会被git跟踪,因此将存在于您结帐的任何分支中。