Как работает git, когда два пира одновременно отправляют изменения на один и тот же пульт - PullRequest
42 голосов
/ 10 января 2011

Я новичок в git, я обычно использую P4, у которого есть центральный репозиторий, в то время как git - это распределенная VCS.

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

Однако, насколько я понимаю, git является внутренним хранилищем ключей / значений, очень похожим на текущую популярную базу данных NOSQL, особенно Couch-DB, которая поддерживает репликацию p2p.

На самом деле я хочу спросить, как конфликтует процесс git в случае, когда клиенты вносят изменения в удаленный репозиторий git? Пуш отклонен?

Из ответа Марка я думаю, что толчок должен быть отклонен.

1 Ответ

68 голосов
/ 10 января 2011

Короткий ответ

Да, один из толчков будет отклонен - ​​какой бы ни был позже, даже если это всего лишь микросекунда, как упоминает Джефроми в своем комментарии.Однако он будет отклонен, потому что удаленный репозиторий видит, что история более поздней отправки не включает в себя историю более ранней, а не потому, что видит какой-либо конфликт в передаваемом контенте.

Подробнееподробный ответ

Обычно толчок будет отклонен, если он не «перемотает» ветвь в терминологии Git.Это означает, что если ваш мастер находится в точке A, а удаленный репозиторий - в точке B, то отправка будет успешной только в том случае, если B является предком A.удаленный репозиторий позволяет это, но это не типичный случай.)

В описываемом вами случае, предположим, что все три репозитория изначально имеют одинаковую историю:

P -- Q -- R

И вы добавили коммитS:

P -- Q -- R -- S

... в то время как кто-то еще добавил коммит T:

P -- Q -- R -- T

Если этот другой человек первым добирается при нажатии (то есть Git на сервере обрабатываетсначала их push), затем их push будут приняты, потому что R является предком T, поэтому удаленный репозиторий также будет иметь историю P -- Q -- R -- T.Если вы впоследствии попытаетесь нажать, вы получите ошибку, потому что T не является предком S.Как правило, при обнаружении этой ошибки ! [rejected] вы либо запускаете git pull, либо git pull --rebase, чтобы убедиться, что вы опережаете мастер в удаленном хранилище.

git pull создаст коммит слияния M чтобы ваша история выглядела следующим образом:

P -- Q -- R -- T -- M
           \       /
            -- S -

... в то время как git pull --rebase повторно применяет изменения, которые вы внесли поверх T, для создания нового коммита, S':

P -- Q -- R -- T -- S'

В любом из этих случаев вы сможете снова нажать, потому что T является предком как M, так и S'.(Предполагается, что в это время никто больше не подталкивал!)

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

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

Замечание о вашей точке хранения ключа / значения

В то время как база данных объектов Git реализована как хранилище ключа / значения, которое отображает имена объектов (также называемые хешами или значениями SHA1)содержание объектов, по моему опыту, люди, изучающие Git, легко делают запутанные предположения о том, как Git ведет себя, когда они слышат, «это как ключевое значениеруда "- звучит так, как будто это может произойти в вашем случае, поэтому я бы предположил, что размышления о Git на этом уровне не самый полезный подход для понимания этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...