문제

I have two git repos that are forks of each other and I need to occasionally import commits from one to the other.

For example:

git-repo1 has this directory structure:

repo1/project1/src

repo1/project2/src

while git-repo2 has the following directory structure:

repo2/src/

What I'd like to do is take a series of commits and generate patches only for commits that altered files within a particular subdirectory (say repo1/project1/src) and ignore all commits that only alter files anywhere else.

Or alternatively, generate patches for all the commits, but only apply the patch IF it alters files within a particular directory.

I need to preserve the metadata about the commits so playing with git diff doesn't seem like a viable option.

The directory structure between the forked git repos differs.

Is there a straight forward way to do this?

UPDATE1

I see this question (How to apply a git patch from one repository to another?) in terms of coping with differing directory structures.

But what if the patch speaks of modifying files that simply do not exist? I would like to ignore such changes.

도움이 되었습니까?

해결책

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

will spit the commits in series that affect that subdirectory into mystuff.patch

Then,

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

and

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

will strip out all the hunks outside that directory. You can apply with

git am justmystuff.patch

with -pn and --directory=new/path/to as desired.

(edit: EOD --> \EOD so the cat above doesn't try to substitute)

다른 팁

if the two repositories have common history (they are both forked from the same repository, but have evolved differently), you could use cherry-picking to import commits selectively from one branch to another.

create a local repository with two remotes (your two diverging repositories)

find the commits in repositoryA that touch certain files

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

cherry-pick those commits into the branch of repositoryB

 git checkout repoB/master
 git cherry-pick a34256f

I tried few different methods found in here and other answers but didn't find a solution fitting for me. This is what I found out.

You can give git format-patch a path as an argument so that it'll create patch only for only those paths.

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

The command git rev-list --max-parents=0 HEAD is used to fetch the initial commit ref from the repository

Applying the patch can be done with

git am git.patch

In my case I also wanted to skip one directory level when applying the patch because I was moving one whole directory from a repository to a separate repository. git apply which gets used by git am has a flag -p<n> which removes leading path components from the diff paths. The default is 1, so git am -p2 git.patch did the work for me.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top