towi
towi

Reputation: 22337

git push a sub-directory into another main repo

I have a big main project with several directories as subtrees.

I want to push the changes in one specific subtree to its origin, which is a separate repository.

The trouble seems to be, that the current subtree I want to push does not originally came from the repository I want to push into. It came from a different repo, via the subtree guides I found by googling. It just looks very similar.

Big project layout, where important_subtree is the thing I am worried about.

~/devel/bigproject
  .git/
  some_subtree/
  other_subtree/
  important_subtree/
    abc.txt
    efg.txt   <--- new version
    hij.txt

And the important_subtree is "strongly related" to that repo:

~/devel/important
   .git/
    abc.txt
    efg.txt   <--- old version
    hij.txt

Now ~/devel/bigproject/important_subtree/efg.txt has changed and I want to push the important_subtree onto the repo ~/devel/important. So afterwards ~/devel/important/efg.txt also has the changes.

The only thing I managed to do is to push push everything in bigproject into important, which is obviously not what I want. Only the changes in the subtree should be pushed.

Upvotes: 5

Views: 5666

Answers (3)

jeremyjjbrown
jeremyjjbrown

Reputation: 8009

This is no longer so complex, you can just use the git filter-branch command on a clone of your repo to cull the subdirectories you don't want and then push to the new remote.

git clone <ORIG_REPO_DIR> <NEW_REPO_DIR>
cd <NEW_REPO_DIR>
git filter-branch --prune-empty --subdirectory-filter <THE_SUBDIR_TO_MAKE_NEW_ROOTDIR> master
git push <MY_NEW_REMOTE_ORIGIN_URL> -f .

Upvotes: 4

Clueless
Clueless

Reputation: 4042

I would recommend the git-subtree addition to git. It adds a git subtree split command that does what you want.

git subtree split --prefix=important_subtree --branch=backport <subtree merge SHA1>^.. --onto=<imported SHA1> --rejoin
git push ~/devel/important backport:master

This cherry-picks the changes in bigproject since you merged important as a subtree, taking only those that modified important_subtree/. It then applies them as new commits on top of the commit you imported from ~/devel/important and creates a branch backport that you can push back in the normal way. Also --rejoin makes it so you don't need to use commit IDs in the future if you want to repeat the process on more changes.

There is more explanation on the author's blog post.

Upvotes: 3

Uwe Geuder
Uwe Geuder

Reputation: 2315

Pushing with different branches can be a very tricky thing.

Maybe the easiest way would be:

  1. Clone your "important" repo once more from the server.
  2. In your "bigproject" produce patches, which contain exactly the changes you intended to push in the first place (e.g. git format-patch) (you might need to make "smaller" commits in a side branch first, if your original commits mix files that should be pushed and such files that shouldn't)
  3. In your new clone of "important" apply the patches (git am)
  4. push the new clone of "important" to its default remote master. Now the push is just a simple fast forward and should not cause trouble.

Upvotes: 1

Related Questions