{"thread":{"id":"20081","subject":"Proposed config addition: submodules.denyNonFastForward","startedAt":"2009-07-10T19:50:04Z","lastAt":"2009-07-10T23:26:36Z","messageCount":2,"participants":["R. Tyler Ballance","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"117793","messageId":"20090710195004.GA2371@starfruit.corp.slide.com","threadId":"20081","inReplyTo":null,"subject":"Proposed config addition: submodules.denyNonFastForward","fromName":"R. Tyler Ballance","fromEmail":"tyler@slide.com","sentAt":"2009-07-10T19:50:04Z","receivedAt":"2009-07-10T19:50:04Z","isPatch":false,"sender":{"key":"tyler@slide.com","avatar":null},"body":"In my previous thread regarding submodules \"Manasging submodules on\nlarge multi-user projects\" I feel that some things were left largely\nunresolved. My options given were:\n\n  * Use repo (and retrain users)\n  * Use Avery's git-subtree(1) addition (and potentially retrain)\n\nAfter discussing some of the pitfalls that I've had with submodule\ndeployment with a kindred spirit in the #github channel, we came to the\nconclusion that submodules would be very usable if one could implement a\n\"submodules.denyNonFastForward\" configuration.\n\n\nTHE ERRORCASE:\n--------------\nThe majority of problems with submodules comes from PEBKAC, where users\ndon't run `git submodule update` and/or the often execute `git commit -a` \nwith nary a concern for whether it's a good idea or not. I concede that\nthese are systemic organizational changes, but I find changing software\nto be well within the acheivable, whereas changing people I've\ndiscovered is near-impossible. \n\nProblems occur in this scenario:\n\n            -sub@A-  -sub@B-\n[master] ------*--------*------->\n                \\        \\\n        [branch] `--------`---X (commit -a)\n\nIn the second merge from master to branch, if the user neglects to\nexecute `git submodule update` and then executes the commit at 'X' they\nwill inadvertantly change the index for the submodule to roll it back to\n\"A\" instead of keeping it at \"B\" where it should be.\n\n\n\nTHE POTENTIAL SOLUTION (and it's problems)\n------------------------------------------\nThe implementation details behind submodules.denyNonFastForward are\ncertainly not simple. \n   * Is it a server-side (bare repo) config value or a client side config value? \n     (I'm assuming it fits best client side). \n   * What if you have a submodule and you explicitly need to roll it\n     back to a previous version of the submodule?\n   * Does this cross the line of separation between super- and\n     sub-module? Currently ths super (from my understanding) does not \n     contain or maintain any \"knowledge\" of the sub-module, it merely \n     is aware of a particular commit to detach the head to.\n\n\nWith the weekend coming up, I have some available coding time, and\ncertainly have no problems attempting to come up with a patch set to add\nthis configuration value, but I do need some guidance as to whether it\nfits into Git conceptually and whether it's technically feasible.\n\n\nCheers\n\n-R. Tyler Ballance\nSlide, Inc.\n"},{"id":"117806","messageId":"7vskh4t903.fsf@alter.siamese.dyndns.org","threadId":"20081","inReplyTo":"20090710195004.GA2371@starfruit.corp.slide.com","subject":"Re: Proposed config addition: submodules.denyNonFastForward","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-10T23:26:36Z","receivedAt":"2009-07-10T23:26:36Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"R. Tyler Ballance\" <tyler@slide.com> writes:\n\n> In my previous thread regarding submodules \"Manasging submodules on\n> large multi-user projects\" I feel that some things were left largely\n> unresolved. My options given were:\n>\n>   * Use repo (and retrain users)\n>   * Use Avery's git-subtree(1) addition (and potentially retrain)\n>\n> After discussing some of the pitfalls that I've had with submodule\n> deployment with a kindred spirit in the #github channel, we came to the\n> conclusion that submodules would be very usable if one could implement a\n> \"submodules.denyNonFastForward\" configuration.\n\nPerhaps it was obvious to _you_ and that was why you omitted mentioning\nit, but it is unclear when you envision this configuration would kick in.\n\nDo you deny changing the commit bound at path \"sub\" from B to X if X is\nnot a descendant of B (e.g. A in your example) when the user does \"git add\nsub\"?  When the user makes such a change into a commit?  When the user\npushes a history that contains such a change to the remote repository?\n\nI suspect that it is quite common for a library-ish project to have two\nbranches, v1.0 and v2.0, that are _not_ strictly fast forwards.  In this\nrespect, git.git is not a norm but is an exception, where 'maint' is\nalways a subset of 'master', causing v1.X.Y always be a subset of\nv1.X.(Y+1).\n\nAnd you may want to bind such a project to your project as a submodule.\n\nDuring the evolution of _your_ superproject, at some point you would\ndecide to switch from using v1.0 line to v2.0 line of the submodule, and\nthat won't be a fast forward.  On the other hand, when you are in control\nof both submodule and superproject, it is reasonable to worry about the\nfast forwardness of your submodule like you depicted in your ERRORCASE\nscenario.  Your project may use both kinds of submodules, which leads me\nto guess that this shouldn't be a single submodule.denyFastForward, but\nshould be a per submodule variable, submodule.$name.denyFastForward,\nregardless of at what stage the check kicks in.\n\nAlso it is plausible that your submodule people are working actively and\nfrom time to time break their tip, and you as a superproject person may\nhave to temporarily revert to an older and more stable commit from the\nsubmodule history until things stabilize on their end.\n\nThe submodule history may look like this:\n\n ---A---B---C---...---G\n\nwhere A was a bit stale but proven one, B was a nice bleeding edge but\nlater turned out to be broken, and the submodule people are working\ntowards the goal of producing a good one G.\n\nYour superproject's history may first bind B, hoping that submodule people\ndid a great job.  But then you discover it was not ready and you have to\nstep back to A temporarily, in order to be able to continue in the\nmeantime.  That won't be a fast-forward (you listed this as one of your\n\"problems\").\n\nYou could fork the submodule history to queue a revert of B on top of it,\nto satisfy the fast-forward requirement you are introducing here, and then\nkeep going.\n\n          B' (revert of B, whose tree is the same as A)\n         /       \n ---A---B---C---...---G\n\nWhen submodule people got their act together, you would want to bind\ncommit G as the submodule to your project.  However, B' won't fast forward\nto G, so you will end up making another merge (checkout G and merge B'\nusing ours strategy) in the submodule, again just to satisfy the fast\nforward requirement.\n\n          B'------------G'\n         /             /\n ---A---B---C---...---G\n\nThe implication of this is that your history will never converge with the\none from submodule people.  Unless you have a way to force them to take G'\nas their tip after they complete G, that is.\n\nWhich mekes me think that, even if you _normally_ want to require fast\nforward, it is essential for you to be able to override the check to\nrebind A in place of B, violating the usual fast forward check.\n\n>    * Is it a server-side (bare repo) config value or a client side\n>    config value?  (I'm assuming it fits best client side).\n\nI think the first prototype should be done as a pre-commit hook script.\n\n>    * What if you have a submodule and you explicitly need to roll it\n>      back to a previous version of the submodule?\n\nAn escape hatch is essential, as I discussed above (not just to \"roll B\nback to A\" example, but also to \"switch from v1.0 line to v2.0 line\").\nYou could use \"commit --no-verify\" if you go the pre-commit hook route.\n\n>    * Does this cross the line of separation between super- and\n>      sub-module?\n\nThis is purely a Porcelain issue to support your workflow, and we should\nallow you to express a little bit of Policy like this, if it helps to make\nthe workflow safer/saner.  I think it is too premature to worry about \"the\nline of separation\"; it is not like we would be making this check part of\nthe default behaviour anytime soon.\n\nAnother question not in your list:\n\n     * What should happen if the submodule is not even checked out nor\n       cloned?\n\nThis would happen when a top-level integrator who does not even have to\ncheck out nor modify a particular submodule has to merge two branches that\nhave different commits for a submodule.  Perhaps their common ancestor in\nthe superproject history had a commit B bound at the submodule, and one\nbranch of the superproject kept it as-is while the other branch updated it\nto a different commit A.  The three-way merge will bind commit A in the\nresulting merge commit, but there is no way for the top-level integrator\nwho does not even have a clone of the submodule to see how A and B relate\nto each other.\n\nI think the right answer to the above question is \"ignore the check\".  The\nbranch that changed the submodule from commit B to commit A should have\nknown what it was doing when it made that change, and the top-level\nintegrator should be able to trust that change---that is why he is merging\nthe branch in the first place.\n"}]}