Подтвердить что ты не робот

Умная перестановка, избегающая избыточной работы?

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

Когда я делаю rebase master, Git наивно применяет каждое из коммитов по очереди. Это означает, что мне нужно разрешить каждый из этих коммитов с помощью кончика мастера, хотя в конечном итоге эта работа пропадает.

Какой хороший способ справиться с этой ситуацией? Возможно, я должен просто создать единый патч для всей ветки и применить это к мастеру? Если да, есть ли способ сохранить какую-то историю? Мысли, предложения и т.д.

4b9b3361

Ответ 1

Вы хотите использовать git rerere в сочетании с обучением базы данных rerere из исторических коммитов с использованием rerere-train.sh (возможно, у вас уже есть значение /usr/share/doc/git/contrib/rerere-train.sh). Это позволяет git автоматически использовать разрешения конфликтов слияния, извлеченные из истории.

Предупреждение: вы в основном делаете git переписываете исходный код, слепо используя исторические замены строк, чтобы исправить конфликтное слияние. Вы должны просмотреть все конфликтующие слияния после перезагрузки. Я нахожу, что gitk отлично работает для этого (он будет показывать только разрешение конфликтов как патч для слияний). У меня были только хорошие впечатления от rerere, возможно, вам не повезло. В принципе, если ваша история содержит разбитые слияния (т.е. Слияния, которые технически неправильно выполнены, а затем исправлены в следующих коммитах), вы не хотите использовать rerere из истории, если вы не хотите, чтобы аналогичные сломанные слияния выполнялись автоматически для вас.

Короче говоря, вы просто запустите

git config --global rerere.enabled 1
bash /usr/share/doc/git/contrib/rerere-train.sh --all

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

После того, как вы включили rerere глобально, вам больше не нужно будет учиться в истории в будущем. Функция обучения требуется только для использования rerere после того, как разрешение конфликта уже выполнено до включения rerere.

PS. Я нашел аналогичный ответ на другой вопрос: fooobar.com/questions/435944/...

Ответ 2

Вы можете использовать функцию git rerere.

Вам нужно включить его с помощью git config --global rerere.enabled 1, после чего каждый конфликт, который вы разрешите, будет сохранен для последующего использования, и разрешение будет повторно применено в тех же контекстах.

Вы можете проверить сохраненные разрешения с помощью git rerere diff.

Взгляните на этот учебник для получения дополнительной информации.

Ответ 3

Почему бы не squash удалить лишние патчи вместе с первоначальной интерактивной rebase (сначала переупорядочить их так, чтобы они были вместе), чтобы вы очистили аспекты "изменить, а затем удалить" этой последовательности. Вы можете быть выборочным с помощью ханков внутри фиксации на этом этапе (например, используя git gui). Тогда это даст вам лучшую последовательность для окончательной чистой перестановки.

Ответ 4

(Это мой второй ответ на вопрос. Во втором чтении я думаю, что исходная проблема могла немного отличаться от той, которую я впервые понял.)

Я понимаю этот вопрос, поскольку у вас есть параллон ветвления разработки до master. Обычно этот вид стиля ветки называется ветвями функций, и я определенно рекомендую их использовать.

Всегда нужно стараться, чтобы ветки функций были чистыми. На практике вам нужна ветвь функции, которая совершает, если бы вы никогда не совершали ошибок. Для меня это означает совершение много, а затем git rebase -i, чтобы исправить ошибки, когда я позже узнаю об этих ошибках.

К тому времени, когда ваша ветвь функций готова, она должна выглядеть как

  • Добавить API, чтобы сделать вещь X
  • Исправить существующий API Y для углового случая Z
  • Добавить функцию B с помощью X и Y (также работает в случае Z!)
  • Улучшить функцию B: сделать магический материал E

Вместо

  • WIP
  • WIP2
  • Добавить API
  • Переместить API для выполнения X
  • Добавить функцию B
  • Во второй раз переименуйте параметры для X
  • Функция исправления B
  • Исправить APi для X
  • Фиксировать угловой регистр Z
  • Исправить угловой регистр Z для API Y, также
  • делать магические вещи E
  • передать отсутствующий файл

Если вы затем переадресовываете ветвь вашей функции в последнюю ветвь master, изменения высоки, что только commit Fix existing API Y for corner case Z может вызвать конфликты. Если эта фиксация является минимальным изменением для изменения существующего API, то устранение конфликта должно быть простым. Кроме того, этот конфликт возникает только в том случае, если какой-либо другой фиксатор точно изменил линии, затронутые вашим минимальным изменением.

Если у вас есть ветки веток и ветвей функций, а не слияния (мой предпочтительный стиль - переформатировать, чтобы можно было выполнить быструю перемотку вперед, а затем сделать git checkout master && git merge --no-ff feature-branch-x и задокументировать все это в деле слияния - это позволяет сохранить полную историю ветки и позволяет инструментам GUI легко перемещаться по этой функции, если это необходимо), вы определенно хотите, чтобы сохраняли ваши фишки объектов до перезагрузки этих ветвей до master. Не только ваши перестановки будут проще, но история будет читаема в конечном итоге.

Итак, в приведенном выше примере можно было rebase -i <old-enough-sha1>, а повторный порядок составлял 3 + 4 + 6 + 8, 10, 1 + 2 + 5 + 7 + 9, 11 + 12, где + означает squash. Git позволяет расщеплять и редактировать существующие коммиты тоже, но обычно легче сохранять фиксации очень маленькими, а затем сквошать некоторые из них позже. Обратите внимание, что в этом примере даже исходное число фиксации 10 заканчивается перед первоначальным первым фиксацией. Это нормально и отражает реальность, что ваша реализация не была идеальной. Однако это не нужно хранить в истории версий.

В вашем случае это звучит так, будто у вас есть ветвь функции, где несколько коммитов добавляют и удаляют одни и те же вещи. Скомбинируйте эти коммиты как единую фиксацию (может закончиться без изменений, что хорошо). Восстановите ветвь вашей функции, чтобы она работала только тогда, когда ветвь функции выглядит чистой. Определенно научитесь использовать git gui или какой-либо другой инструмент, который упрощает запись измененных строк вместо файлов. Каждое совершение должно быть изменением, которое изменяет разумную коллекцию вещей. Если вы добавите новую функцию X, то такая же фиксация не должна исправлять существующую функцию Y или добавлять отсутствующую документацию о Z. Даже если эти изменения были внесены в один и тот же файл. Для меня это тот материал, который имел в виду Линус Торвальдс, когда он сказал: " файлы не имеют значения".