Как переформатировать несколько веток одновременно в Git? - PullRequest
0 голосов
/ 29 сентября 2019

Предположим, у меня есть структура веток в Git, которая выглядит как master -> A -> B. То есть A содержит коммиты поверх master, а B содержит коммиты поверх A.

Я хотел бы переформатировать A, не приводя к огромному набору конфликтовв B это нужно будет решить вручную. Если я не ошибаюсь, я могу сделать это с помощью git filter-branch , за исключением того, что я не хочу, чтобы что-либо в master изменилось. (Т.е. я не хочу аннулировать все общедоступные идентификаторы коммитов Git в проекте.)

Есть ли способ git filter-branch только для A и B (или так же хорошо для моегоцель, все ветви в репо кроме master)?

Редактировать: В частности, достаточно ли сделать git filter-branch ... A B? Будет ли это избегать прикосновения к master и поддерживать согласованность A и B друг с другом (т. Е. Переписывать общие фиксации между A и B к одним и тем же идентификаторам фиксации и не позволять им дублироваться или что-то подобноечто).

Ответы [ 2 ]

1 голос
/ 29 сентября 2019

У вас здесь правильное общее представление (о том, как использовать фильтр-ветвь), но неправильный синтаксис. Чтобы получить git filter-branch для копирования (и фильтрации) коммитов, доступных с обоих имен A и B, но не для копирования + фильтрации коммитов, доступных с master, используйте синтаксис:

git filter-branch <options> -- ^master A B

То, что мы делаем здесь, с git rev-list аргументами ^master A B, говорит Git: Найти все коммиты, достижимые из A или B, исключая все коммиты, достижимые из master. Таким образом, если цепочки коммитов идут:

...--o--o--o   <-- master
            \
             o--o--o   <-- A
                    \
                     o--o   <-- B

, например, это выбирает фиксации в средней и нижней строке. Это было бы даже с ^master B или master..B, как в phd-ответе , но это лучше по двум причинам. Во-первых, он по-прежнему выбирает все коммиты из средней строки с помощью:

...--o--o--o   <-- master
            \
             o--o--o   <-- A
                 \
                  o--o   <-- B

(хотя это, вероятно, не ваша структура). Во-вторых, после копирования (и фильтрации) указанных коммитов так, что вы получите:

                     o--o   <-- [filtered copy of commit to which B points]
                    /
             o--o--o   [filtered copy of commit to which A points]
            /
...--o--o--o   <-- master
            \
             o--o--o   <-- A
                    \
                     o--o   <-- B

команда filter-branch переместит все то, что документация звонки положительные отзывы . Положительной ссылкой является та, которая не имеет отрицания перед ней: в этом случае A и B, но не master, поскольку master написано ^master и, следовательно, является отрицательной ссылкой.

Следовательно, это не затронет master (не то, что это все равно будет - его коммит не скопирован), но будет стереть имена A и B так, чтоони указывают на скопированные коммиты.

Обратите внимание, что если вы не хотите вносить изменения в моментальные снимки в двух (в этом примере) B только коммитах, то вы должны написать умныйфильтр, который делает это. (Или использовать фильтр, который не вносит изменений в дерево, но при «переформатировании» я предполагаю, что вы хотите использовать --tree-filter и что-то вроде clang-format на снимках в каждом из различных A коммитовВозможно, более разумно идти вперед и вносить одинаковые изменения форматирования в различные B коммиты.)

0 голосов
/ 29 сентября 2019

git filter-branch ... AB

Нет, это обработает ветви A и B обратно в корневой коммит. Я бы пошел следующим образом:

A_behind_B=`git rev-list --count A..B`
git filter-branch ... master..B # or ^master B
git checkout A
git reset --hard B~$A_behind_B

Подсчитайте, сколько коммитов А отстает от Б. Выполните filter-branch для коммитов от master до Б. Сбросьте А, который будет коммитить за новым Б.

...