{"thread":{"id":"14369","subject":"submodules and interaction with GIT","startedAt":"2008-07-09T13:07:23Z","lastAt":"2008-07-09T13:07:23Z","messageCount":1,"participants":["Pierre Habouzit"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"82718","messageId":"20080709130723.GG23482@artemis.madism.org","threadId":"14369","inReplyTo":null,"subject":"submodules and interaction with GIT","fromName":"Pierre Habouzit","fromEmail":"pierre.habouzit@intersec.com","sentAt":"2008-07-09T13:07:23Z","receivedAt":"2008-07-09T13:07:23Z","isPatch":false,"sender":{"key":"pierre.habouzit@intersec.com","avatar":null},"body":"Let's start with a bit of context. We have this __huge__ \"put everything\nin it\"-repository at work, and we want to strip out core modules and\nintegrate them in our different projects through submodules.  We moved\naway one of our core libraries into its separate git repository, and it\nbecame a submodule in our big fat repository. I believe it's the kind of\nthings we said people should do when they need partial checkouts\n(tree-wise) so I assume the workflow I describe here is decent.\n\nJust to make things clearer, we have two branches in this repository,\n'maint' and 'master'. Maint is the branch for the production product,\nmaster is the one where devel happens. 'maint' is obviously merged into\n'master' on a regular basis.\n\n\nProblem 1: directory/submodule conflicts (aka D/S)\n---------\n\nOur first problem was that git doesn't deal with D/S conflicts well.  To\nmigrate our repository, I went into 'maint' and did:\n\n  $ git rm -rf corelib\n  $ git submodule add -b corelib/master -- <our-repo> corelib\n  $ git commit -asm'replace corelib with a submodule'\n\n  Then I went into 'master' and did:\n\n  $ git merge maint\n\nHere it failed horribly because it claimed that the merge would clobber\nuntracked files like corelib/.gitignore which was a previously tracked\nfile in the huge repository and is now tracked in the submodule.\n\nI worked that around by having an intermediate commit that removes\n'corelib' in 'master'. Unpretty, but works.  Later, when other\ndevelopers updated their trees, they had all kinds of really distateful\nissues related to D/S conflicts.\n\n\n\nProblem 2: integration with git-checkout\n---------\n\nWhen using submodules, when I do updates to the corelib, like fixing a\nbug, hence I want it to appear in 'maint', I go to maint and basically\ndo:\n\n  $ cd corelib\n  $ git fetch\n  $ git reset --hard origin/corelib/master # so that I have the fix\n  $ cd ..\n  $ git commit -asm'update corelib for bug#nnn'\n\nWhen then I `git checkout master`, the corelib submodule had no\nmodifications in 'maint' but remains in its 'maint' state when I go to\nmaster instead of what I would like: see it be checkout to its 'master'\nstate, and refuse to checkout if the submodule cannot perform the\ncheckout.\n\nI'd really like git checkout -m to also perform a git checkout -m in\nsubmodules.\n\nAnd along the road, one has a lot of frightening errors:\n    fatal: cannot read object b8f1177da31281682feb79c9d4290a88edf067ae 'corelib~Updated upstream': It is a submodule!\n\n\nI quite understand that in presence of submodules git checkout works\nbecomes quite harder as you have to check for every submodule plus\nyourself to know if you can perform the checkout, but I don't really see\nwhy it can't be done.\n\n\nProblem 3: similar problem with git-reset\n---------\n\nReally, I type git reset --hard all the time to undo my local changes.\nAnd I know while typing that it destroys local changes. Really, it\nshould reset the submodules to their supposed state as well.\n\n\n\nProblem 4: merging\n---------\n\nWhen merging two branches, there is a strategy that I believe is\napplicable for submodules. If one of the two submodules states is a\ndirect ancestor from the other, then the merge result shall be the\ndescendant.\n\nWhen revisions are not in direct line, then it shall be a conflict.\n\n\nProblem 5: fetching\n---------\n\n`git fetch` should fetch submodules too. Arguably, if you type `git\nfetch REMOTE` then any submodule that has a corresponding \"REMOTE\"\nconfigured should fetch it.\n\n\nNotes:\n-----\n\nWhen you cannot know something required for conflicts handling e.g.,\n(because you haven't enough history for the submodules) the command\nshall fail asking the user to fetch the incriminated submodules. IOW\nwhen you perform any action that involves submodules, each submodules\nmust be queried to know if it can performs the action, and git shall\nfail if it's not the case and do nothing.\n\nWrt most of the behaviours I described, I would be fine if those were\nenabled only by a configuration flag in the .gitmodules, and that user\ncan override in their .git/config. We could have a\nsubmodule.<module>.commandsMustRecurse setting to tell\nfetch/reset/checkout/... to behave like I said with this module. I\nbelieve that true should be the default.\n\nNon initialized submodules should be considered as always up to date for\nall of this, so that people that don't want to waste bandwidth for this\nor this submodule can work peacefully.\n\n\n\nOkay, I'm sure there are tons of other uses of submodules out there for\nwhich this is an overkill, but if we really intend seriously to tell\npeople \"do use submodules to avoid having incredibly huge repositories\"\nlike we did in the past, we should really improve the overall usability.\n-- \n·O·  Pierre Habouzit\n··O                                                madcoder@debian.org\nOOO                                                http://www.madism.org\n"}]}