问题 git staging和多个分支之间的提交


我显然根本不懂git。这就是我得到的:

git branch  (outputs that I'm on master)
git checkout -b foo
echo "next line" >> file (file is an existing file)
git add file (stages)
git checkout master
git status (shows that file has "next line" and is staged!!)
git commit (commits the changes that were staged on branch foo!!)
git checkout foo

这是踢球者。 foo现在不显示对工作目录中的文件所做的任何更改或暂存。

所以看起来 - 你所做的任何改变,包括修改文件和升级,都发生在所有分支上。当您COMMIT到特定分支时,除了您提交的分支之外的所有其他分支上将丢弃这些更改。

这实际上是怎么回事?有人能让这对我有意义吗?这听起来像是完全疯狂的行为,很明显我没有得到让这件事变得明智的设计理念。

编辑显式示例:

$ mkdir element
$ cd element
$ git init
Initialized empty Git repository in /home/dan/element/.git/
$ echo "one" >> one
$ git add one
$ git commit -m msg
[master (root-commit) 36dc8b0] msg
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 one
$ git checkout -b fire
Switched to a new branch 'fire'
$ echo "next line" >> one
$ git checkout master
M       one
Switched to branch 'master'
$ cat one
one
next line
$

这与git pro书明显矛盾:

This is an important point to remember: Git resets your working directory to look like the snapshot of the commit that the branch you check out points to. It adds, removes, and modifies files automatically to make sure your working copy is what the branch looked like on your last commit to it.


6285
2018-05-11 16:55


起源

我的回答是否有助于澄清事情?我认为它早于您的编辑,但我不完全确定。 - larsks


答案:


当你在哪个分支上并不重要  一个文件,只有当你 承诺 它。所以,如果你这样做:

git add file
git checkout master
git commit

您已将文件提交到主分支。

这是一个完整的例子,带有输出。我们从一个新的存储库开始:

$ git init
Initialized empty Git repository in /home/lars/tmp/so/repo/.git/

在这一点上,我们正在 master 分支,我们还没有添加任何文件。我们添加一个文件:

$ date > file1
$ cat file1
Fri May 11 13:05:59 EDT 2012
$ git add file1
$ git commit -m 'added a file'
[master (root-commit) b0764b9] added a file
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 file1

好的,我们现在有一个分支(master)一次提交。让我们创建新的分支:

$ git checkout -b foo
Switched to a new branch 'foo'
$ git branch
* foo
  master
$ ls
file1

现在我们将添加一行 file1

$ date >> file1
$ git status
# On branch foo
# 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:   file1
#
no changes added to commit (use "git add" and/or "git commit -a")

这表明该文件已被修改,但尚未暂存。让我们暂存文件并提交它:

$ git add file1
$ git commit -m 'made a change'
[foo 761bed9] made a change
 1 files changed, 1 insertions(+), 0 deletions(-)

并重新运行 git status

$ git status
# On branch foo
nothing to commit (working directory clean)

此时,该文件如下所示:

Fri May 11 13:05:59 EDT 2012
Fri May 11 13:07:36 EDT 2012

如果我们切换回 master 分支,我们将看到没有第二行的文件的早期版本:

$ git checkout master
Switched to branch 'master'
$ cat file1
Fri May 11 13:05:59 EDT 2012

对文件的更改将与提交它们的分支隔离。

在您更新的示例中,这...

$ git checkout master

...不生成错误,因为此时两者中的“一”版本 master 和 fire 是相同的。工作目录中的更改同样适用于任一版本。


9
2018-05-11 17:11



是的 - 如果你在一个分支上以原子方式处理提交,那么一切都在这个例子中起作用,这对我来说很有意义。如果您修改并且可能在没有提交的情况下暂存然后切换分支,那么您将进入我在第一篇文章中发生的这种奇怪的循环状态。道德根本不会在没有承诺的情况下切换分支吗?但是:如果我在另一个方向上执行此操作并在master上工作并切换到分支火,它会给我一个错误: error: You have local changes to 'one'; cannot switch branches.  不知道为什么我没有从另一个方向得到这个错误。 - djechlin
在运行之前是否实际跟踪了文件 git add?您可以使用显示实际命令和输出的示例存储库重新调整您的问题吗?通常,提交或通常是常见的 藏 切换分支前的更改。 - larsks
编辑问题以显示完整对话而不仅仅是命令。我会看看藏匿 - 似乎我不明白git中的“浅”分支是如何的。我不明白为什么git让我做一个脏的结账。 - djechlin
我已经添加了这个答案。 - larsks
我想我明白了。只要分支指向同一工作目录,您就可以自由切换。一旦你提交了一个并且他们指向不同的快照,git将不允许你进行脏检查。 - djechlin


登台区域也称索引对所有分支都是通用的,这可以解释您的观察结果


2
2018-05-06 00:56