4

Let's say I have two repos, repo A and repo B, which contains a folder with code similar to the code in repo A (doesn't really matter how this actually has happened, but OK, let's assume I've just copied contents from A).

Now I want following:

  • To work just as I got used to in repo A
  • To set and additional remote repo pointing to repo B, but pushing and pulling only this subfolder.
  • To push, when it needed to this repo B.

So, basically, I'm looking for the cheapest way to have something like reversed sparsed check out.

shabunc
  • 23,119
  • 19
  • 77
  • 102
  • 2
    Probably relevant: http://stackoverflow.com/a/17864475/20270 – Hasturkun Sep 02 '13 at 09:19
  • 2
    Have you tried submodules yet? – aragaer Sep 02 '13 at 09:20
  • @aragaer I've tried submodules a couple of years ago for quite a different set of tasks and have no idea how it can help in this very case. – shabunc Sep 02 '13 at 09:23
  • Basically - you'll have 3 repos - A, B and "common". – aragaer Sep 02 '13 at 09:26
  • @Hasturkun, an excellent link, thank you! It is definitely related, but does not solves the issue - I mean yes, you can create a separate repo from existing folder, but living simultaneously with both of repos is a challenge. – shabunc Sep 02 '13 at 09:34
  • 1
    @shabunc: I think the whole subtree thing might work for you. The references on the answer I linked might help, eg. http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/ . AFAICT, it should allow what you want. – Hasturkun Sep 02 '13 at 10:04
  • How about extracting that folder to a common **repo C**, and using sumbodules? Or, simply cloning into **A** and **B** (with a *post-clone* hook for example), and setting the folder on ignore on the upper level repo? – rlegendi Sep 04 '13 at 13:05
  • rlegendi, using third repo id definitely something I want to avoid. As for ignoring all the upper level repo - let me think a bit) – shabunc Sep 04 '13 at 13:09
  • 1
    @aragaer Add the submodule approach as an answer, because IMO it's the correct way to do this. – KurzedMetal Sep 04 '13 at 14:48
  • @shabunc Submodules were designed with this exact situation in mind. You might be able to achieve it some other way, but it probably isn't going to be pretty. – Max Sep 04 '13 at 18:56

4 Answers4

2

One approach is to set up 3rd repository containing the code common for both projects, then use that repository as submodule in both repository A and B.

However if I understand your question right, the whole A repository is that "common" code. In that case there's no need in 3rd repository and you can simple add A as a submodule inside B.

aragaer
  • 17,238
  • 6
  • 47
  • 49
  • The way I understood is: the "library"-like code already has its own repository, which is repo B, and the "project" code which is using that "library" is repo A. He doesn't need to create a third repo, just replace a directory in "project" repo A with a submodule from the "library" repo B – KurzedMetal Sep 04 '13 at 15:02
  • 1
    After some careful reading I feel that it maybe the other way - A is 'library', while one subfolder in B contains that library code. – aragaer Sep 04 '13 at 15:17
  • I believe you are correct (and should edit your answer accordingly). There is no need for a third repo as you can simply add A as a submodule in B. – Max Sep 04 '13 at 18:57
2

It seems exactly the kind of problem git-subtree1 tries to solve.

cd repoB
git subtree pull -P folder {repoA URL} {repoA branch}
... edit test commit... 
git subtree push -P folder {repoA URL} {repoA branch}
milton
  • 988
  • 6
  • 19
  • Please, edit your answer, since in it current state it looks like a comment in best case. – shabunc Sep 04 '13 at 15:09
  • Why using a modified git version if the standard git can manage this use case? I did read its documentation, It just didn't convince me, as I see it, `git-subtree` cons outweigh the pros. – KurzedMetal Sep 04 '13 at 15:18
  • It's not a modified version, it's already integrated at newest revisions of the official git repository. – milton Sep 04 '13 at 18:08
2

You can add a ref for and so publish anything in a repo. So, to maintain a separate branch that tracks the main branch's subfolder, add this to your commit ritual:

# in your commit ritual (no need to be mainbranch-specific, 
# this will detect changes and add the tracking commits only as necessary),
if [ `git rev-parse mainbranch:path/to/subfolder` \
      != `git rev-parse subfolderbranch:path/to/subfolder` ]; then 
    git commit-tree -p subfolderbranch -p mainbranch \
              mainbranch:path/to/subfolder <<<"tracking mainbranch subfolder" \
    | xargs git update-ref -m"tracking mainbranch subfolder" refs/heads/subfolderbranch 
fi
jthill
  • 55,082
  • 5
  • 77
  • 137
  • as far as I understand this snippet of code, we first comparing revision list in both repose and if they are not identical, we are trying to sync them by migrating commits from B (big repo). Neat solutions as so far is the best one. But what about pushing to repo B? – shabunc Sep 05 '13 at 09:30
  • 1
    No, this is in whatever repo is generating new commits to mainbranch. Whenever the subfolder in a mainbranch commit is different than the last one, it generates a new commit on the subfolder-tracking branch. Pushing doesn't change, you just push the new branch along with the mainbranch. – jthill Sep 05 '13 at 13:00
1

Clone repoA to create your new repoB. Then, set the assume-unchanged bit for everything except the subfolder:

git update-index --assume-unchanged *
git update-index --no-assume-unchanged <subdirectory>

Note: the file/directory argument must NOT begin with a . or a /

After that, you can delete everything except the subfolder. Due to the assume-unchanged bit git will not notice that. Now work as it this would be a normal repository. You may copy your changed files from the old repoB to this one.

Note that pushes and pulls may create files that are not in the subfolder again. To prevent that, you can create a hook to delete everything except the subdirectory.

functionpointer
  • 1,411
  • 1
  • 13
  • 18