{"thread":{"id":"23878","subject":"Sharing a file between projects","startedAt":"2010-05-22T16:24:31Z","lastAt":"2010-05-24T08:55:33Z","messageCount":2,"participants":["Patrick Rutkowski","Jonathan Nieder"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"142106","messageId":"D3671E72-7B04-446B-86A8-48761FD476E4@gmail.com","threadId":"23878","inReplyTo":null,"subject":"Sharing a file between projects","fromName":"Patrick Rutkowski","fromEmail":"rutski89@gmail.com","sentAt":"2010-05-22T16:24:31Z","receivedAt":"2010-05-22T16:24:31Z","isPatch":false,"sender":{"key":"rutski89@gmail.com","avatar":null},"body":"Say that I've got several projects called P1, P2, and P3. Each project in a separate git repo. Each project has file foo.cfg. However, whenever I change foo.cfg in P1, I have to make the same change to the foo.cfg in P2 and P3.\n\nThey really are separate projects which ought to have their own git repos, I don't want to force a user checking out P1 to also check out P2 and P3.\n\nBut I also don't want to have to manually make sure that foo.cfg is synced among all three projects.\n\nAny ideas here guys?\n\n-Patrick\n"},{"id":"142187","messageId":"20100524085533.GA25227@progeny.tock","threadId":"23878","inReplyTo":"D3671E72-7B04-446B-86A8-48761FD476E4@gmail.com","subject":"Re: Sharing a file between projects","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-05-24T08:55:33Z","receivedAt":"2010-05-24T08:55:33Z","isPatch":false,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Patrick Rutkowski wrote:\n\n> I also don't want to have to manually make sure that foo.cfg is\n> synced among all three projects.\n\nGive foo.cfg its own repo, since it seems it is independently useful.\nThen you could use it from your other projects P1, P2, P3 in one of\nthe following ways:\n\na. Installation script (‘make install’) copies foo.cfg to some\n   standard filename, such as /usr/share/foo/foo.cfg or /etc/foo.cfg.\n\n   Then use it from there, e.g. by tracking an ordinary symlink\n   /etc/foo.cfg -> foo.cfg in the P1, P2, P3 trees.\n\nb. Occasionally pull from the foo.cfg project into P1, P2, and P3.\n\nc. Teach P1, P2, P3 build scripts to clone the foo.cfg repo and grab\n   foo.cfg\n\nd. Add the foo.cfg repo as a submodule of the P1, P2, and P3 repos.\n\nExamples:\n\n a. most libraries.  I guess /usr/lib/tclConfig.sh and\n    /usr/lib/pkgconfig/* are good examples.\n b. Debian X build system: http://git.debian.org/?p=pkg-xorg/xsfbs.git\n d. gnulib: http://git.savannah.gnu.org/cgit/gnulib.git/tree/users.txt\n\nRelevant git features:\n\n a. If there is a symlink in the worktree, the only information that\n    git will notice is “symlink to <target>”.  The content of the\n    target does not enter the tracked tree.\n\n b. Merging from an independent project is a perfectly okay way to add\n    files.  Merging again is a good way to update them.\n\n    Merging changes back to a smaller project is not so well\n    supported[1].\n\n d. Using submodules works like this:\n\n    . ‘git clone --recursive’ to grab all the relevant files at once\n\n    . Do work within submodules and ‘git push’ to publish your work\n\n    . Git will remember the ‘last tested commit’ so new changes to\n      foo.cfg do not break new clones of P1, P2, and so on until\n      someone in each project explicitly acks them.\n\n    . See git-submodule(1) for details (and please let us know about\n      confusing or missing details in that manual).\n\nThoughts?\nJonathan\n\n[1] Suppose I have been working for a while as in case (b) above [time\nflows from left to right]:\n\n foo.git:    F --- G --- H --- I\n                    \\           \\\n P1: A --- B --- C - M --- D --- N --- O\n\nNow I make a change to foo.cfg (Q) and commit and push it in P1.git,\neven though it ought to have been done in foo.git so it could be used\nby P2 and P3, too.  Oops.\n\n foo.git:    F --- G --- H --- I\n                    \\           \\\n P1: A --- B --- C - M --- D --- N --- O --- Q\n\nNow I could try to merge P1 into foo.git, but unfortunately the result\nwould be a commit incorporating all development from both branches,\nincluding the files from P1 that are _not_ foo.cfg.\n\nI use git-filter-branch(1) to recover, producing an alternate history\ntracking only changes to foo.cfg:\n\n      F --- G --- H --- I\n             \\           \\\n        A' ---M'----------N' --- Q'\n\nUh, the desired history looks more like the following:\n\n     F --- G --- H --- I --- Q'\n\nbut git filter-branch --prune-empty is not sophisticated enough to do\nthat.  Maybe someone can chime in with a script for this situation.\n\nNow I merge the rewritten history into foo.git:\n\n foo.git:    F --- G --- H --- I --- Q'\n                    \\           \\\n P1: A --- B --- C - M --- D --- N --- O --- Q\n\nand use ‘merge -s ours’ to indicate that the new changes have already\nbeen incorporated into P1.\n\n foo.git:    F --- G --- H --- I ------ Q' ---.\n                    \\           \\              \\\n P1: A --- B --- C - M --- D --- N --- O --- Q - R\n"}]}