Git автоматически объединяет изменения из другой ветки в master - PullRequest
27 голосов
/ 13 ноября 2011

У меня проблема с ветвлением Git. Всякий раз, когда я делаю изменения в ветви, все эти изменения отражаются в основной ветви, даже если я не вызывал явную команду слияния.

Например,

Я создал ветку "Панель инструментов" git checkout -b dashboard

Затем я внес изменения в один из моих файлов (скажем, route.rb), и теперь я переключился на master git checkout master

Теперь, когда я открываю route.rb, я вижу изменения в ветке приборной панели. Зачем? У меня есть какие-то настройки git, которых там быть не должно?

Ответы [ 3 ]

28 голосов
/ 13 ноября 2011

Когда вы вносите изменения, эти изменения существуют только в вашем рабочем дереве вплоть до момента, когда вы их фиксируете.

Когда вы переключаете ветки, Git перенесет изменения в вашем рабочем дереве в новую кассу. Это часто полезно, когда вы замечаете, что работали не с той веткой.

Существует даже недавнее обсуждение этого "неожиданного" поведения в списке рассылки Git по этому поводу. Процитирую Junio:

"J.V." gmail.com> пишет:

ОК, так что "дерево работы" - это новый термин для меня. Я думал, что мы были в изоляции песочницы под названием "ветки" и изменения, сделанные в ветке, останутся в независимо от этой ветви.

Не думайте о "ветвях" как об изолированных песочницах .

Скорее, "ветви" - это то место, где должны быть независимые государства записано .

Записанные состояния существуют только в репозитории git, и использовать его содержимое (например, просмотр в пейджере или браузере, редактирование в редакторе, запуск компилятор, ...), вам нужно материализовать содержимое ветка где-то в файловой системе. Такой набор файлов на Файловая система образует рабочее дерево. Акт так называется "проверить ветку". [...]


Редактировать

На всякий случай, если вышеуказанная ссылка становится недействительной

Проблема

Unexpected git behaviour 

--- 
# First create a local git repo 

$mkdir gitexample 
$git config --global user.name "my name" 
$git config --global user.email "me@me.com" 
$git init 
$git add . 
$git commit -m 'initial commit' 

# Create/Edit an empty file 
$vi readme.txt 

# add a single line: "this was added in the master branch." 
$git commit -a 

# create and checkout a new branch (from master) 
$git branch test 
$git checkout test 

# edit the readme.txt file and do not commit 
# add the text:  "this was added in the test branch.", save and exit 
$vi readme.txt 

#now switch back to master 
$git checkout master 
$cat readme.txt 

#You will see both lines in the master.   

Question #1: 
        Why was this line added in the *master branch? 


--- even further surprising 
In the master branch, now do a commit 
$git commit -a 

cat readme.txt ( you will see the line in the master now that was added in the test branch ) 

Question #2: 
        Why did this happen? 

# Now switch back to the test branch 
$git checkout test 
$cat readme.txt 

You will only see the one line: "This was added in the master branch" 

Question #3: 
        Why did this happen? 

and NOT the line added in that branch: "this was added in the test branch" <= this line is gone 

What is the reason for this? 

1) Why do I see uncommitted changes in the branches made off master in the master branch? 
2) Why, if I commit them in the master, do the disappear in the branch in which they were made? 

This is confusing, I would think the * master branch would be left untouched.  This would solve issue #2. 

Ответить

On Fri, Nov 11, 2011 at 12:55:04PM -0800, Jvsrvcs wrote: 
> Unexpected git behaviour 
> 
[ ... switch branches with local modifications ...] 
> #You will see both lines in the master.   
> 
> Question #1: 
> Why was this line added in the *master branch? 
> 

It wasn't. that line was added in the working directory. When you 
switch branches, if the file in the tip of the current branch and the 
file in the tip of the target branch don't differ, it's safe to keep 
your local changes, so git does. This is to support the use-case where 
you start editing a file when the wrong branch is checked out and want 
to change to the right one. 

> 
> --- even further surprising 
> In the master branch, now do a commit 
> $git commit -a 
> 
> cat readme.txt ( you will see the line in the master now that was added in 
> the test branch ) 
> 
> Question #2: 
> Why did this happen?
... [show rest of quote]
... [show rest of quote]
Because you told git to commit the file with that modification in it. 

> 
> # Now switch back to the test branch 
> $git checkout test 
> $cat readme.txt 
> 
> You will only see the one line: "This was added in the master branch" 
> 
> Question #3: 
> Why did this happen? 

Because the file in the 'test' branch only has that line. As you said 
yourself, you edited the file but didn't commit. 

> 
> and NOT the line added in that branch: "this was added in the test branch" 
> <= this line is gone 

Again, that line wasn't added in any branch but in the working 
directory. The active branch was 'test', but doesn't magically mean 
that uncommitted changes travel with it. 
12 голосов
/ 13 ноября 2011

Когда вы редактируете файлы в вашем рабочем каталоге, вы не редактируете файлы "git" (любой ветки или мастера) в этот момент, вы просто редактируете свои локальные файлы или "рабочий каталог", как он называется.

Все файлы "git" (которые вы зафиксировали) находятся в каталоге .git.Макет соответствует вашим папкам, и здесь также хранятся ветки. Sidenote: в нем хранятся фактические файлы (сжатые), в отличие от инструментов контроля версий, таких как svn, в которых хранится дельта (разница)

Поэтому, когда вы редактируете файл, вы фактически не редактируете ни мастер, нифилиал, вы просто редактируете файл.Если вы не делаете коммит, а затем переключаете ветки, у вас все равно будет этот файл, и его изменения будут видны, даже если вы «переключились» на новую ветку.Это то, что обычно сначала удивляет людей.

Лучший совет здесь - зафиксировать / игнорировать / отменить все ваши изменения перед переключением веток, чтобы избежать этих проблем.Также такие инструменты, как gitx (Mac) m и gitg (Ubuntu) облегчают эти задачи тем, кто любит gui, и у них также есть хорошие предупреждения о таких проблемах.

В любой момент вышеприведенного git status очень полезени может сказать вам, что в настоящее время не используется ни для какого git-репо (будь то мастер или ветки)

gustavotkg также дает хороший совет, используя git stash для этих проблем.

9 голосов
/ 13 ноября 2011

Если вам нужно переключиться на основную ветку без фиксации текущей ветки, вы можете использовать git stash

git stash # all changes will be queued
git checkout master
# do whatever you need in master
git checkout dashboard
git stash pop # get all changes queued back to branch
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...