В Mercurial, если вы попытаетесь сделать пуш, и в основном репо были сделаны коммиты, вы вынуждены вытащить и слиться.
И Git, и Mercurial работают практически одинаково. Когда в удаленном репо были сделаны новые коммиты, git push
прервется с:
$ git push
To /home/mg/tmp/git/repo-1
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to '/home/mg/tmp/git/repo-1'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again. See the
'Note about fast-forwards' section of 'git push --help' for details.
Mercurial также прерывается в этой ситуации:
$ hg push
pushing to /home/mg/tmp/hg/repo-1
searching for changes
abort: push creates new remote head 436b0ce25d42!
(you should pull and merge or use push -f to force)
Пока все хорошо. В Git теперь вы запускаете git pull
, а в Mercurial вы можете запускать hg fetch
. Это восстановит и объединит новые наборы изменений и будет работать одинаково в обеих системах.
Проблема в том, что когда вы переходите к фиксации своих изменений, в наборе изменений, который вы нажимаете, содержатся файлы, которые вы были вынуждены объединить.
Вы не трогали эти файлы, но история показывает, что вы их модифицировали.
Я думаю, вы не понимаете, что Mercurial показывает вам. Обе системы работают со снимками полного репозитория, поэтому обе системы заставят вас вносить изменения в файлы, которые вы не коснулись при слиянии. Коммит Git Merge также «содержит» все файлы, которые не были изменены - на них ссылается объект дерева, на который ссылается коммит.
Поскольку обе системы используют моментальные снимки, возникает вопрос "кто что изменил?" имеет смысл только при сравнении двух снимков. Для набора изменений слиянием существует два интересных сравнения: с первым родителем и со вторым родителем.
Разница между Mercurial и Git заключается в том, что для набора изменений слияния патч не отображается:
$ git log -p -1
commit 8cdbbef1b6f0fc8e01997f6842b7f249d066a30c
Merge: b77058e e99e303
Author: Martin Geisler <mg@aragost.com>
Date: Mon Jan 23 14:09:09 2012 +0100
Merge branch 'master' of /home/mg/tmp/git/repo-1
, тогда как Mercurial всегда показывает патч против первого родителя:
$ hg log -p -l 1
changeset: 3:94060588f0a5
tag: tip
parent: 2:06d00ad5063b
parent: 1:436b0ce25d42
user: Martin Geisler <mg@aragost.com>
date: Mon Jan 23 14:01:25 2012 +0100
summary: Automated merge with file:///home/mg/tmp/hg/repo-1
diff --git a/b b/b
new file mode 100644
--- /dev/null
+++ b/b
@@ -0,0 +1,1 @@
+b
Это показывает, что файл b
не присутствовал в первом родителе слияния. Другими словами: это, вероятно, произошло от второго родителя. Используйте hg diff -r "p2(3):3"
или hg diff -r "3^2:3"
, чтобы проверить это. В Git вы будете использовать git diff "8cdbbef^2" 8cdbbef
для сравнения со вторым родителем.
Обратите внимание, что обе системы показывают одинаковое для git log b
и hg log b
: набор изменений слияния отсутствует в журнале для файла, если файл не был фактически изменен как часть набора изменений слияния. Файлы обычно изменяются в наборах изменений слияния, потому что конфликты должны быть разрешены до того, как слияние будет зафиксировано.