2016-04-19 2 views
1

Вот воспроизводимый пример проблемы я ввязался:Re-сращивание после «Selective» или «Частичная» Слияние

установки

mkdir test-git 
cd test-git 
git init 
echo 'Hello, world.' > file1.txt 
git add . 
git commit -m 'init commit' 
git branch branch2 
git checkout branch2 
echo 'Hello, universe' > file1.txt 
echo 'Foobar' > file2.txt 
git add . 
git commit -m 'commit 2' 

Я хотел объединить branch2 в мастер но только изменения в file1.txt, так вот что я сделал:

git checkout master 
git merge branch2 --no-commit --no-ff 
git reset -- file2.txt 
git commit -m 'Partially Merged Branch2 into Master!' 

так вот, где я понял, что не могло бы быть хорошим язь a ... Предположим, я передумал, и теперь я хочу объединить файл file2.txt. Я могу запустить:

git merge branch2 

Ответ: Уже уточненный.

Если я бегу git diff branch2 --name-status он возвращает D file2.txt, так что я думаю, когда я unstaged file2.txt это отслеживали это как удаление? Я до сих пор не понимаю, почему я не могу слиться, и он не добавит файл (я, очевидно, не очень хорошо понимаю алгоритм слияния git).

К сожалению, мой сценарий в настоящее время намного сложнее, поэтому я не могу точно отменить фиксацию. Есть ли простой способ устранить различия между master и branch2, без переписывания истории?

ответ

2

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

Поведение имеет свои причины. Предположим, что один из них внесет дополнительное изменение в file2.txt в branch2 после 1-го слияния слияния, а затем выполнить другое слияние branch2 в master (довольно типичная ситуация, не так ли?). Что следует рассматривать как правильное состояние file2.txt. Я ожидаю, что второе слияние должно содержать только изменения, сделанные между двумя слияниями, не так ли? Но вы желаете какое-то другое поведение, когда git собирает все изменения до file2.txt, которые не были применены до сих пор с начала истории. Это было бы очень неприятно.

Тем не менее вы можете сделать «альтернативное слияние». То есть, перейдите к фиксации до слияния на ветке master (в вашем примере «init commit»), а затем снова введите git merge.

Если перестройка истории не подходит для ваших нужд, вы можете создать новую ветку b3 при этом фиксации, выполнить слияние, а затем слить b3 обратно на мастер. Определенно, вы получите конфликт слияния на file2.txt и должны решить его, предоставив для него «правильный вариант».

+0

Ya, что полностью имеет смысл. Несмотря на использование git в течение многих лет, я начинаю понимать, что у меня действительно нет такого твердого понимания, как я, хотя и сделал. Не переписывал бы мастер в init commit, а затем перезаписывал историю причин, чтобы переписать? – NSjonas

+0

Действительно будет. Обновлен ответ. – user3159253