Как я могу лучше обрабатывать коммиты, загрязняющие "закрытую" ветку в git? - PullRequest
3 голосов
/ 12 апреля 2011

Мы новички в git в моей компании, пришли в git из Subversion, и в выходные мы столкнулись с ситуацией с веткой в ​​нашем репозитории, когда были сделаны коммиты для публичной версии ветки, которую мы не делали 'не хочу там.У нас было:

A -> B

И затем мы получили плохие коммиты, чтобы поместить ветку в:

A -> B -> C -> D

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

В Subversion единственный выход из подобной ситуациидолжен был зафиксировать! D и! C, чтобы вы получили:

A -> B -> C -> D -> !D -> !C

, который возвращает меня к B, но заставляет меня двигаться вперед по временной шкале для ветви, так что любой, кто имеет удаленный доступ к ветви, синхронизируетс главным репозиторием получал бы C и D и затем отменял их, чтобы в конечном итоге получить логически похожую версию B (но не B - назовите ее B ').

Я сталкивался с этим решениемдля возврата коммитов в git , который казался идеальным: он вернул бы наш публичный репозиторий к A -> B.Но это означало, что любой клон этой ветки на чьей-либо рабочей машине был бы очень неправильным, и каждый должен был бы повторно клонировать.Мое исправление составило:

git checkout thebranch
git reset --hard <<commit # associated with commit B>>
git push --force

Я закончил путь по вышеуказанной ссылке, и это вызвало переполох:

a) Вы можете выбросить историю коммитов в публичном хранилище.с помощью git, как это, буквально переписываем коммит-реальность;

b) Каждый должен был повторно клонировать, чтобы не рисковать повторным внедрением C -> D в ветку (или новую ветвь этой ветвичто мы хотели создать).

Я думаю, что должен сделать:

git revert HEAD~2
git commit
git push

Но это оставило бы ветвь как A -> B -> C -> D -> E, и это действительно должноУ меня нет C -> D -> E, потому что он должен быть закрыт.

У меня есть три вопроса:

  1. Как я мог бы справиться с уборкой лучше?Использовать revert вместо reset?Какова лучшая практика для загрязнения веток?
  2. Действительно ли push --force возвращенной ветки действительно уничтожили историю в публичном хранилище?Или git откатился к B, но сохранил запись C -> D, и что в какой-то момент я сделал возврат к B?Это определенно не показывает возврат в журнале фиксации, но, возможно, запись о моих действиях хранится где-то еще?
  3. Как вы обрабатываете «закрытые» ветки в git так, что эти изменения не могли иметьполучил там в первую очередь?У нас действительно был тег, примененный к хранилищу при коммите B, и люди должны использовать тег branch +, чтобы получить исходный текст для релиза, но это все еще страшно, чтобы изменения отображались в ветке ветки, которая не должна иметьизменения в нем после коммита B. И кто-то, переходящий из ветви для выпуска патча, мог легко пропустить тег и вытащить C -> D в свою новую ветку.

Ответы [ 2 ]

5 голосов
/ 12 апреля 2011

Вы должны использовать теги для релизов («закрытые ветки») и веток для разработки («открытые ветки»).Это альтернативное решение для исправления вашей проблемы (вы можете просто использовать тег для выпущенного кода) и способ предотвратить эту проблему в будущем.

Пока вы разрабатываете v3.1, вы можете иметьваша ветка v3.1.После завершения v3.1 отметьте последний коммит и переименуйте ветку в следующую ветку разработки (v3.2).Помните: Git не Svn!Ветвь - это только указатель на коммит.Удаление ветки не удаляет коммиты (но если эти коммиты не включены в другую ветку, они будут зависать, поэтому вы должны сделать тег перед удалением ветки).

Если вы хотите разработатьпатч для v3.1 (v3.1.1), затем вы создаете ветку по тегу v3.1:

git checkout -b v3.1.1 v3.1

Это будет понятнее вашим разработчикам (ветки предназначены для разработки, а теги - для релизов).) и не допустить повторного появления этой проблемы.


Действительно ли сила принудительного восстановления обращенной ветви действительно уничтожила историю в общедоступном хранилище?

Нет.Если бы вы создали тег или ветвь для коммита D, тогда эта ветвь была бы в порядке.Используйте git reflog, чтобы увидеть последние изменения в голове.Эти коммиты должны быть там.(Или git fsck.)


Для хорошего обсуждения git, который не использует другие системы контроля версий в качестве основы для понимания, попробуйте PeepCode's Git Internals .Это не бесплатно, но я думаю, что лучше понимать git, кроме централизованного контроля версий.( Git Community Book выглядит как хорошая бесплатная альтернатива.)

1 голос
/ 12 апреля 2011

Относительно пункта 2: Нет;сброс ветви (локально или на сервере) никогда не уничтожит историю.В git ветвь похожа на метку, которая просто указывает на конкретную фиксацию (и метка автоматически перемещается вперед, когда ветка извлекается и делается новая фиксация).Сброс ветви просто означает, что метка перемещается назад;сами коммиты остаются, но становятся «невидимыми», если на них нет других ветвей.В этом случае их можно восстановить с помощью git reflog, который покажет вам хэши всех коммитов, даже тех, у которых нет ветки.Затем вы увидите, что «удаленные» коммиты все еще там.Единственное, что может их уничтожить - это git gc (который также спорадически запускается самим git), который удаляет несвязанные коммиты.

Когда вы сбрасываете ветку на более раннюю точку и принудительно толкаете ее, другие разработчикиможете сбросить свою ветку с помощью git fetch -f origin branchname:branchname;нет необходимости повторно клонировать (однако, они должны сначала извлечь другую ветку, чтобы предотвратить запутывание индекса при принудительном извлечении).Однако это приведет к тому, что они «потеряют» коммиты (опять же, они могут быть найдены с помощью git reflog), если они сделали коммиты на ветке после тех, которые вы случайно нажали.Вероятно, это не проблема для вас, так как ветка должна была быть закрыта в любом случае, но если это произойдет, они могут создать новую ветвь перед принудительным извлечением;тогда новая ветвь все еще будет указывать на их самые новые коммиты, и git rebase может пересаживать коммиты в соответствующую ветвь.

...