大多数时候,当我尝试签出另一个现有分支时,Git不允许我在当前分支上有一些未提交的更改。因此,我必须先提交或隐藏这些更改。

然而,Git偶尔允许我签出另一个分支而不提交或存储这些更改,它将把这些更改携带到我签出的分支。

这里的规则是什么?更改是阶段性的还是非阶段性的有关系吗?对我来说,把这些变化带到另一个分支没有任何意义,为什么git有时允许这样做?也就是说,它在某些情况下有用吗?


当前回答

如果新分支包含的编辑与特定更改文件的当前分支不同,那么它将不允许您切换分支,直到提交或存储更改。如果在两个分支上更改的文件是相同的(即,该文件的提交版本),那么您可以自由切换。

例子:

$ echo 'hello world' > file.txt
$ git add file.txt
$ git commit -m "adding file.txt"

$ git checkout -b experiment
$ echo 'goodbye world' >> file.txt
$ git add file.txt
$ git commit -m "added text"
     # experiment now contains changes that master doesn't have
     # any future changes to this file will keep you from changing branches
     # until the changes are stashed or committed

$ echo "and we're back" >> file.txt  # making additional changes
$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
    file.txt
Please, commit your changes or stash them before you can switch branches.
Aborting

这既适用于未跟踪的文件,也适用于跟踪的文件。下面是一个未跟踪文件的示例。

例子:

$ git checkout -b experimental  # creates new branch 'experimental'
$ echo 'hello world' > file.txt
$ git add file.txt
$ git commit -m "added file.txt"

$ git checkout master # master does not have file.txt
$ echo 'goodbye world' > file.txt
$ git checkout experimental
error: The following untracked working tree files would be overwritten by checkout:
    file.txt
Please move or remove them before you can switch branches.
Aborting

一个很好的例子,为什么你想要在分支之间移动,同时进行更改,如果你在master上执行一些实验,想要提交它们,但还不是master…

$ echo 'experimental change' >> file.txt # change to existing tracked file
   # I want to save these, but not on master

$ git checkout -b experiment
M       file.txt
Switched to branch 'experiment'
$ git add file.txt
$ git commit -m "possible modification for file.txt"

其他回答

您有两个选择:隐藏您的更改:

git stash

然后再把它们拿回来:

git stash apply

或者将更改放在一个分支上,这样您就可以获得远程分支,然后将更改合并到该分支上。这是git最伟大的地方之一:你可以创建一个分支,提交给它,然后在你所在的分支上获取其他更改。

你说这没有任何意义,但你这么做只是为了在拉之后可以随意合并它们。显然,您的另一个选择是提交分支的副本,然后执行拉取。假设你不想这样做(在这种情况下,我对你不想要分支感到困惑),或者你害怕冲突。

如果新分支包含的编辑与特定更改文件的当前分支不同,那么它将不允许您切换分支,直到提交或存储更改。如果在两个分支上更改的文件是相同的(即,该文件的提交版本),那么您可以自由切换。

例子:

$ echo 'hello world' > file.txt
$ git add file.txt
$ git commit -m "adding file.txt"

$ git checkout -b experiment
$ echo 'goodbye world' >> file.txt
$ git add file.txt
$ git commit -m "added text"
     # experiment now contains changes that master doesn't have
     # any future changes to this file will keep you from changing branches
     # until the changes are stashed or committed

$ echo "and we're back" >> file.txt  # making additional changes
$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
    file.txt
Please, commit your changes or stash them before you can switch branches.
Aborting

这既适用于未跟踪的文件,也适用于跟踪的文件。下面是一个未跟踪文件的示例。

例子:

$ git checkout -b experimental  # creates new branch 'experimental'
$ echo 'hello world' > file.txt
$ git add file.txt
$ git commit -m "added file.txt"

$ git checkout master # master does not have file.txt
$ echo 'goodbye world' > file.txt
$ git checkout experimental
error: The following untracked working tree files would be overwritten by checkout:
    file.txt
Please move or remove them before you can switch branches.
Aborting

一个很好的例子,为什么你想要在分支之间移动,同时进行更改,如果你在master上执行一些实验,想要提交它们,但还不是master…

$ echo 'experimental change' >> file.txt # change to existing tracked file
   # I want to save these, but not on master

$ git checkout -b experiment
M       file.txt
Switched to branch 'experiment'
$ git add file.txt
$ git commit -m "possible modification for file.txt"

我最近也面临着同样的问题。我的理解是,如果你签入的分支有一个你修改过的文件,它碰巧也被那个分支修改和提交了。然后git会阻止你切换到分支,在你提交或存储之前保证你的变化安全。

我也在这件事上挣扎了一段时间,我想给出我的答案。首先,我对这件事的理解来自这里:https://medium.com/swimm/a-visualized-intro-to-git-internals-objects-and-branches-68df85864037

问题是:

然而,Git偶尔允许我签出另一个分支而不提交或存储这些更改,它将把这些更改携带到我签出的分支。 这里的规则是什么?更改是阶段性的还是非阶段性的有关系吗?对我来说,把这些变化带到另一个分支没有任何意义,为什么git有时允许这样做?也就是说,它在某些情况下有用吗?

当你从任何其他分支创建一个分支时,你只是创建了一个指向同一个提交的指针,所以除非你已经提交了你已经开始工作的任何更改,否则你将指向同一个提交,因此git将允许你以这种方式更改分支。只有当你向新分支提交任何更改时,不同分支之间的提交才会开始不同,如果有任何未提交的更改,git在尝试签出这些分支时会报错。

正确答案是

Git checkout -m origin/master

它将来自源主分支的更改与本地甚至未提交的更改合并。