Git постановка и фиксация между несколькими ветвями

Я явно не понимаю 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 не показывает никаких изменений, внесенных в файл в рабочий каталог или поставил.

Так выглядит: любые изменения, которые вы делаете, включая изменение файлов и постановку, происходят с ветками ALL. и когда вы 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.

Ответ 1

Неважно, какая ветка вы используете, когда добавляете файл, только когда вы его совершаете. Поэтому, если вы это сделаете:

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

... не генерирует ошибку, потому что в этот момент версия 'one' в обоих master и fire идентична. Изменения в рабочем каталоге одинаково хорошо применимы к любой из версий.

Ответ 2

Промежуточная область aka index является общей для всех ветвей, что объясняет ваше наблюдение