Git允许我在不提交更改的情况下切换分支

27

我正在学习Git,跟着教程走。我在分支seo_title上有未提交的更改,对于mission.html文件。我执行了git checkout master,期望会看到关于更改未提交的警告信息,例如Changes not staged for commit, no changes added等等,但是实际上切换分支时没有出现这些警告信息,而是显示了以下消息:

M       mission.html
Switched to branch 'master'

当我运行git diff mission.html命令时,它显示出来的结果是工作目录中仍包含我在切换到其他分支时所做更改的内容。 我错过了什么吗? 值得一提的是,我正在Windows上使用Git Bash。

编辑:mission.html文件的更改也没有被加入到暂存区域。

编辑2:我以为得票最高的答案是正确的,但进一步调查后发现它与我看到的行为不符。 以下是我正在进行的操作的更详细描述:

top_directory(master) > git branch new_branch_1
top_directory(master) > git branch new_branch_2
top_directory(master) > git checkout new_branch_1
< p >打开 notepad++,修改 resources.html 文件,保存< /p >
top_directory(master) > git status
# On branch new_branch_1
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed
#   (use "git checkout -- <file>..." to discard changes in wo
#
#       modified:   resources.html
#
no changes added to commit (use "git add" and/or "git commit
top_directory(new_branch_1) > git checkout new_branch_2

我希望git能够提醒我去存储或提交,因为new_branch_1和new_branch_2有不同版本的resources.html文件,但是它没有任何警告就直接切换到了新分支,并且还将未提交的更改一并带来了:

M       resources.html
Switched to branch 'new_branch_2'
top_directory(new_branch_2) > git status
# On branch new_branch_2
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   resources.html
#
no changes added to commit (use "git add" and/or "git commit -a")

有没有一种模式或设置,可以使其表现为这样而不是警告?还是我对场景仍然存在误解?

编辑3:我现在明白了。排名第一的答案是正确的,可以看看我的最后一条评论。


问题是什么?是的,git允许检出其他分支。这非常有用。如果您错误地从错误的分支编辑了文件,则可以检出正确的分支并在那里提交。 - balki
5
我感到困惑的是:我原本以为checkout会尝试更新工作目录以匹配新分支。但是,当它发现存在未提交的更改(这些更改在更新工作目录时将丢失)时,它会中止checkout操作。至少在先前的课程中,教程表明了这一点(而我也亲眼见证了)。 - burgerB
可能是因为您在主分支之后没有进行任何提交。因此,所有分支都指向相同的提交对象。当您从不同的分支检出时,实际上是从当前分支的相同提交中检出。 - nn0p
我认为这个答案 https://dev59.com/z2Qo5IYBdhLWcg3wXeX5#16113552 解释得非常好:“只要你改变工作目录的提交不会覆盖本地未提交的更改,Git 就可以让你检出其他分支(或标签或 SHA1 哈希)。” - Matthew
5个回答

36

你上一次尝试切换分支并保留本地更改时看到的与现在不同的行为是由于文件更改不同引起的。

假设我们有一个名为“readme”的分支,在其中您对文件(例如README.md)进行了一些更改。现在,您已经切换回主分支并对其他文件进行了一些工作,以致有本地更改。如果您尝试在不提交更改的情况下切换回“readme”分支,它将允许您这样做。为什么?因为切换到“readme”分支不会覆盖任何本地更改。

但是,如果您修改了主分支上的README.md文件,那么当您尝试执行

git checkout readme 

您将会遇到

error: Your local changes to the following files would be overwritten by checkout: README.md
Please, commit your changes or stash them before you can switch branches.

因为你已经对README.md做出了更改,这需要合并。


1
这可能会对编程有些帮助:这里 - Nick Tomlin
你所描述的是我期望的,但不是我看到的。我会在问题中添加更多描述。 - burgerB
没事了,我重新阅读了一遍,现在我明白了。现在我这样想:这个警告就像合并时的冲突警告一样,只不过它发生在你的分支中有未提交的更改并且你正在切换分支时,而不是提交。如果提交和合并不会产生冲突,那么它将允许您在不提交/隐藏的情况下切换分支。 - burgerB
这种行为有什么好处吗?如果默认情况下被拒绝会更友好。是否可以将其作为设置来实现? - huggie
@huggie 为什么 Git 要这样做呢?你在 dev 分支上有一些文件。如果它们被暂存了,那么 Git 会比较两个版本,并在存在冲突时给出警告。这很自然,但如果你的文件没有被暂存,那么 Git 就不应该关心它们。你还期望 Git 做什么?删除未暂存的文件吗?如果你需要暂时删除,就把它们藏起来。如果你根本不需要它们,就删除它们,但不要指望 Git 询问你是否要删除它们,因为决定(未暂存)更改是你的工作。 - Alireza Mohamadi

16

这是正常的行为。如果你不想在新检出的分支上保留修改过的文件,那么请将它们进行存储。像这样:

# on branch dev
$ git stash
$ git checkout master

# do stuff on master

# back to dev
$ git checkout dev
$ git stash pop

2
Git能让你切换到其他分支(或标签或SHA1哈希),只要你更改工作区域的提交不覆盖你本地未提交的更改。

在你的情况下,分支master的工作区将与你从中切换的当前分支的末尾存在的版本相同。在此更改分支时,Git无需触及工作副本(至少对于missing.html而言),因此可以让你保留本地修改。

如果您确实尝试了检出提交,其中工作区域中的missing.html版本与当前分支中提交的版本不同,则git将显示类似于以下错误消息:

$ git checkout some-other-branch
error: Your local changes to the following files would be overwritten by checkout:
        missing.html
Please, commit your changes or stash them before you can switch branches.
Aborting

0

Git - the stupid content tracker。它只是使用工作树快照进行操作。主要要求-您应该能够重建工作树。它当然会更新。但是,如果在两个分支中修改的文件相同-为什么不允许切换呢?如果您错误地这样做了,可以通过重建先前的状态来切换回去,没什么大不了的。但是,如果分支中的文件不同,则需要合并内容,这就是它坚持提交更改的原因,否则将无法返回。


0

这很明显,如果你改变了一个在你想要切换的分支中没有改变的文件,因为checkout的语法是将所有索引和工作目录带到你的新分支中,所以它们会出现在你的新分支中。而如果有冲突,你需要合并这些文件,这意味着一旦合并后,如果你切换回旧分支,那么它已经是合并后的版本而不是你之前的版本,你会失去它。因此,为了确保你保留旧的更改,它不会让你这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接