Как я могу генерировать / применять git-патчи только для коммитов, которые изменяют определенные файлы

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

Например:

git-repo1 имеет такую ​​структуру каталогов:

repo1/project1/src

repo1/project2/src

в то время как git-repo2 имеет следующую структуру каталогов:

repo2/src/

Я хотел бы сделать серию коммитов и генерировать патчи только для коммитов, которые изменяли файлы в определенном подкаталоге (скажем, repo1/project1/src) и игнорировать все коммиты, которые изменяют только файлы где-либо еще.

Или, альтернативно, генерируйте патчи для всех коммитов, но применяйте патч только в том случае, если он изменяет файлы в определенном каталоге.

Мне нужно сохранить метаданные о коммитах, поэтому играю с git diff не кажется приемлемым вариантом.

Структура каталогов между разветвленными репозиториями git отличается.

Есть ли прямой способ сделать это?

Update1

Я вижу этот вопрос ( как применить git patch из одного хранилища в другое?) С точки зрения совмещения с различными структурами каталогов.

Но что, если патч говорит об изменении файлов, которые просто не существуют? Я хотел бы игнорировать такие изменения.

3 ответа

Решение

git rev-list --reverseseries-- repo1/project1/src/ \
| xargs -I@ git format-patch --stdout @^! >mystuff.patch

будет разбивать коммиты последовательно, которые влияют на этот подкаталог в mystuff.patch

Затем,

cat >mystuff.sed <<\EOD
/^(From [0-9a-f]{40}|diff --git )/!{H;$!d}
x
/^From /b
${h;s,.*--,--,;x}
\,^diff[^\n]* [ab]/repo1/project1/src/,!{$!d;x;b}
${p;x}
EOD

а также

sed -Ef mystuff.sed mystuff.patch >justmystuff.patch

удалит все фрагменты за пределами этого каталога. Вы можете подать заявку с

git am justmystuff.patch

с -pn а также --directory=new/path/to по желанию.

(edit: EOD -> \EOD, чтобы кот выше не пытался заменить)

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

создайте локальный репозиторий с двумя удаленными (ваши два расходящихся репозитория)

найти коммиты в репозитории, которые касаются определенных файлов

 $ git checkout repoA/master
 $ git log sub/dir/ectory
 a34256f ...

Вишни выбрать эти коммиты в ветке репозитория B

 git checkout repoB/master
 git cherry-pick a34256f

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

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

      git format-patch HEAD --root $(git rev-list --max-parents=0 HEAD) --stdout -- repo1/project1/src/ > git.patch

Команда git rev-list --max-parents=0 HEADиспользуется для получения исходной ссылки коммита из репозитория

Применение патча может быть выполнено с помощью

      git am git.patch

В моем случае я также хотел пропустить один уровень каталога при применении патча, потому что я перемещал весь каталог из репозитория в отдельный репозиторий. git applyкоторый используется git amимеет флаг -p<n>который удаляет ведущие компоненты пути из путей сравнения. По умолчанию 1, поэтому git am -p2 git.patchсделал работу за меня.

Другие вопросы по тегам