Как я могу генерировать / применять 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 --reverse
series
-- 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
с -p
n
а также --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
сделал работу за меня.