Git принудительное нажатие: как предотвратить изменение других пользователей - PullRequest
3 голосов
/ 18 мая 2011

Мне часто приходится использовать git reset и git rebase, чтобы изменить несколько недавних коммитов (изменить порядок, объединить несколько коммитов в один, ...).Это требует использования опции силы при нажатии.К сожалению, это также может перезаписать изменения других пользователей в удаленном репозитории.

Почему мне нужно переписать историю?Потому что мы проделали большую работу в ветви функций (если конкретнее, перейдем от использования Swing к SWT) и должны сделать ее как можно более короткой.Чтобы достичь этого, мы часто обнаруживаем, что некоторые коммиты должны идти к мастеру до того, как ветвь функции будет разветвлена.

Как заставить принудительный git push завершиться ошибкой, если я не получил последние изменения изудаленный репозиторий?

Ответы [ 2 ]

4 голосов
/ 18 мая 2011

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

git не может на самом деле отличить между тем, что вы переписали коммиты, но имеете обновленный репозиторий, и тем, что вы не переписали коммиты, но имеете коммиты, которые должны быть объединены перед нажатием. Способ обнаружения актуального push-сообщения заключается в простой проверке того, что каждый коммит в ссылке-получателе находится в истории ссылки, которую вы нажимаете; это известно как перемотка вперед. Когда вы перебазируете, вы удаляете коммиты из вашей локальной ветки и создаете новые, похожие коммиты. git не может точно определить, что эти новые коммиты равны старым коммитам в истории, видит это как ожидающее слияние и требует переопределения этой силы и перезаписывает все, что уже находится в репозитории назначения .

Так что, если вы заставите, вы перезапишите все, что находится в пункте назначения. Это по замыслу. Более того, другие люди, извлекающие информацию из вашего хранилища, тоже увидят проблемы из-за этого. Допустим, вы изменили порядок коммитов в вашем хранилище:

A-------B-------C oldmaster
 \
  ------C'------B' master

Если какой-то другой пользователь имеет локальную копию oldmaster и извлекает ее из master, git попытается объединить эти две ветви. Это приведет к двойному применению патчей в C' и B'. Нехорошо. Git может иногда обнаруживать эти проблемы во время слияния, но даже если он сливается правильно, у вас останется:

A-------B-------C------D master
 \                    /
  ------C'------B'----

А теперь ваши перебазированные коммиты вернулись из мертвых.

Использование rebase там тоже не помогает; с тем же успехом вы можете получить:

A------B------C------C'------B'

В простом случае, подобном этому, git может обнаружить двойные патчи и удалить их, но это не гарантируется.

Итак, в заключение: не перебрасывайте коммиты, которые были сделаны видимыми для других. Делайте все необходимые изменения, если это все еще частная ветвь, которую вы храните локально, или когда это публичная ветвь с большими предупреждениями, в которых говорится: « РАЗРАБОТКА ФИЛИАЛ - МОЖЕТ БЫТЬ ПЕРЕПИСАНО - НЕ ОСУЩЕСТВЛЯТЬ РАБОТУ НА ЭТОМ ФИЛИАЛЕ ». Но в тот момент, когда кто-то еще строит на нем верх, перестаньте возиться с историей.

Если вам абсолютно все время приходится возиться с историей с несколькими пользователями, возможно, вам будет удобнее работать с веткой функций как пакет исправлений, используя StGIT , вина , topgit или аналогичный. Затем вы можете работать с ними как с патчами, переупорядочивать патчи все, что вы хотите (но не изменять сами коммиты!), А затем, когда придет время выдвигать изменения в восходящем направлении, линеаризовать патчи поверх исходного восходящего потока. филиал.

2 голосов
/ 18 мая 2011

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

Прежде всего, вам действительно нужно переписать историю?В большинстве случаев правильный ответ - оставить историю как есть и добавить только новые коммиты.

Если вы действительно думаете, что вам нужно изменить порядок коммитов (скажем, чтобы соответствовать стандарту кодирования?) И вы не можете обучатьлюди, которые сделали эти коммиты, чтобы сделать их правильно с первого раза, вы рассматривали другую схему?Имейте одно центральное «благословенное» хранилище, но позволяйте только инженерам релиза (или инженеру по интеграции, или команде, или как вы хотите их называть) продвигаться к нему.Обычные пользователи публикуют репозитории в других местах (обычно на своих рабочих станциях), и вместо того, чтобы нажимать, они просят инженера-релиза отказаться от них.Затем релиз-инженер просматривает изменения, реорганизует и объединяет их по мере необходимости, запускает любые тесты или другие необходимые шаги и отправляет результат в благословенное хранилище.

...