Git заставляет вас тянуть изменения к наконечнику? Ваш пуш включает эти файлы? - PullRequest
1 голос
/ 21 января 2012

В Mercurial, если вы попытаетесь нажать и в основном репо были сделаны коммиты, вы вынуждены вытащить и слить.push содержит файлы, которые вы были вынуждены объединить.

Вы не трогали эти файлы, но история показывает, что вы их изменяли.

Имеет ли Git такое же поведение?Или он достаточно умен, чтобы знать, что вы не изменяли эти файлы, поэтому нет смысла хранить его в своей истории.

Ответы [ 5 ]

2 голосов
/ 23 января 2012

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

1 голос
/ 23 января 2012

Этот ответ был существенно пересмотрен после подробного обсуждения с @ LaurensHolst.


У вас есть выбор: включать коммиты слияния или нет.Git по умолчанию включает коммиты слияния.Вы также можете установить pull для использования rebase, который создаст линейную историю без фиксации слияния.

Для удаленных веток можно настроить перебазирование вместо слияния:

git config branch.<branch-name>.rebase true

git может установить это автоматическииспользование

git config [--global] branch.autosetuprebase always

Использование rebase для коммитов слияния приводит к тому, что локальные коммиты размещаются после удаленных коммитов без дополнительной фиксации.Это обеспечивает линейную версию истории.git позволяет вам выбирать, какую историю вы предпочитаете.

Аналогичный ответ и объяснение можно найти на Git pull приводит к посторонним сообщениям «Merge branch» в журнале фиксации .

1 голос
/ 21 января 2012

Это достаточно умно, чтобы знать. Ваши коммиты отделены от объединенных коммитов.

1 голос
/ 21 января 2012

Git не будет отображать их в виде патча. Это означает, что вы объединили их, потому что это было необходимо, но ваши коммиты без слияния не покажут изменений в этих файлах. Фактически, git log -p, который покажет коммиты и патчи для каждого, не покажет слияние, если не было конфликтов.

1 голос
/ 21 января 2012

Если вы не трогали файлы, которые были изменены на удаленном компьютере, то git не будет отображать их как конфликтные, и вам не придется их объединять. Так что нет, это не покажет, как если бы вы коснулись этих файлов, если вы этого не сделали.

Кроме того, если вы вообще не хотите, чтобы коммит слияния отображался в вашей истории, вы можете использовать опцию --rebase при извлечении с пульта (см. man git-pull).

...