Есть ли способ заставить git добавить файл из master в 10 других веток? - PullRequest
0 голосов
/ 14 сентября 2018

Есть ли способ сказать git добавить новый файл в каждую другую ветку?

Вместо git checkout <branch>; git merge master для каждой ветви, есть ли ярлык для добавления newfile в каждую ветку?ветвь ниже?

     master
       +-----newfile
       |
      --- 
    /  |  \
   /   |   \
  /    |    \
foo   bar   baz

РЕДАКТИРОВАТЬ: Это сценарий bash (нуждается в некоторой очистке, если он реализован), я придумал, но надеюсь, что есть лучший способ.

MSG='added newfile which contains a method to workaround issue IS-797'
for branch in $(git branch | grep -v master | sed 's#^[ *\t]##g'); do
   echo merging into $branch
   git checkout $branch && git merge master -m "$MSG"
done

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

Есть несколько способов сделать это.Большинство советов в других комментариях / ответах (на момент написания статьи), на мой взгляд, подозрительно.Вот краткое изложение различных вариантов, с плюсами и минусами.

Прежде всего, есть (как минимум) три различных варианта того, как может выглядеть финальная история.У каждого есть свои плюсы и минусы.Вроде, как бы, что-то вроде.Больше похоже на то, что у каждого есть свои минусы, а плюсы в том, что у него нет минусов других способов.

  • Может показаться, что файл был "всегда рядом", так как до этогобыли созданы филиалы.Большим недостатком является то, что это перезапись истории, и это имеет последствия.

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

  • Может показаться, что файл был добавлен один раз, а затем объединен в каждую ветвь.Некоторые люди действительно ненавидят коммиты слияния, и даже если кто-то, кто не особенно ненавидит коммиты слияния, я думаю, что такой подход приводит к хаотичной топологии ветвей.Но это позволяет избежать переписывания истории и будет хорошо работать в будущем;то есть это функционально самый чистый вариант, но эстетически грубый.

Более подробно рассмотрим каждый из них:


История переписывания :

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

Для больших переписываний мой общий совет - координировать со всеми, чтобы установить дату / время, когда все работы будут перенесены в репо.Затем все сбрасывают свои клоны, вы переписываете, и каждый повторно клонирует.Если это не практично, то большая переписка, вероятно, не очень хорошая идея;но если вы все-таки хотите это учесть, прочитайте раздел «восстановление после восходящего повтора» в git rebase документах для получения дополнительной информации о том, что должно произойти.

Хотя rebase, я полагаю,прототипный способ переписать историю, в этом случае это почти наверняка неправильный путь.Если у вас много веток, вам придется делать это много раз.Если у вас сложная история, это становится очень трудно сделать правильно.В частности, он плохо работает со слияниями (даже с недавно добавленными улучшениями).

Вместо этого вы можете использовать git filter-branch.Простой способ с --tree-filter.Вы поместите копию файла где-нибудь за пределами рабочего дерева, затем

git filter-branch --tree-filter 'cp /path/to/stored/copy/of/file path/to/file/in/worktree' -- --all

Затем filter-branch продолжит проверять каждый коммит в вашей истории, выполните команду cp, чтобы добавить файл врабочее дерево для этого коммита и напишите новый коммит с результирующим контентом.Затем он переместит ветки со старых коммитов на новые.Если у вас есть теги и вы хотите, чтобы они тоже перемещались, добавьте аргумент --tag-name-filter, например

git filter-branch --tree-filter 'cp /path/to/stored/copy/of/file path/to/file/in/worktree' --tag-name-filter cat -- --all

Проблема в том, что если ваша история велика, процесс медленный.Вы можете ускорить его, используя виртуальный диск для рабочего дерева (см. Параметр -d), или используя --index-filter вместо --tree-filter (но для этого необходимо использовать различные команды для непосредственного обновления индекса,и это не так просто).


Каждая ветвь добавляет файл

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

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

Для этого вы можете использовать тот же базовый сценарий, что и для слияния, просто заменив команду merge командой cherry-pick.


Слияния

Для этого вы уже составили разумное решение - вам нужен сценарий.Единственное, что я хотел бы отметить, это то, что git for-each-ref часто является более подходящей командой для ввода в сценарий, чем git branch.https://git -scm.com / документы / ГИТ-за-каждый-исх

0 голосов
/ 14 сентября 2018

Если у вас уже есть коммит на master, я просто выбрал бы его в каждой ветке.Это кажется самым простым и надежным сценарием;ошибка в одной ветви должна быть несущественной для других ветвей.

commit='deadbeef'
for branch in $(git branch | sed -n '/master/!s#^[ *\t]##p'); do
   echo "cherry-picking onto $branch"
   git checkout "$branch" && git cherry-pick "$commit"
done

Помимо этого, обратите внимание на предпочтение строчных переменных оболочки, заключая в кавычки, не используя флаг g в sed, когда выожидайте только одно совпадение в каждой строке и избегайте бесполезного использования grep.

Использование \t в сценарии sed не является полностью переносимым;возможно, попробуйте [*[:space:]] вместо [ *\t].

Выбор отдельного коммита Cherry, конечно, также гораздо более специфичен, чем объединение всех master в каждую ветку, что вполне может быть полным нет-нетдля тех, кто борется с этим.

0 голосов
/ 14 сентября 2018

Вы можете использовать git rebase для достижения этой цели, но прочитайте, почему вы не должны использовать git rebase из этой статьи

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