{"thread":{"id":"43158","subject":"Re: [RFC] Two conceptually distinct commit commands","startedAt":"2006-12-04T19:08:22Z","lastAt":"2006-12-06T23:29:35Z","messageCount":13,"participants":["Carl Worth","Jakub Narebski","Theodore Tso","Junio C Hamano","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"298665","messageId":"87d56z32e1.wl%cworth@cworth.org","threadId":"43158","inReplyTo":null,"subject":"[RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-04T19:08:22Z","receivedAt":"2006-12-04T19:08:22Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"[\n  I think the proposal below is original, and more correctly captures\n  the essence of the \"commit interface wart\" than any previous\n  proposal I've made. This proposal is also based entirely on what is\n  useful for all git users, and what I perceive git's conceptual\n  models to be. That is, this proposal concerns what _I_, (as a fairly\n  experienced git user), actually want, without any bias for any\n  assumptions about what an imagined \"new user\" might want. Notably,\n  it does not try to satisfy naive (and likely incorrect) assumptions\n  about git's model.\n\n  Finally, this proposal intentionally uses ludicrously long command\n  names. This is because a discussion of realistically short names\n  triggers the two loaded issues of \"muscle memory\" and which concepts\n  get blessed as \"defaults\". In previous threads, those issues have\n  muddied the conceptual issues I'd like to focus on here. Let's talk\n  about the concepts first, and save discussions of naming for later\n  if necessary.\n]\n\nProposal\n-------\nHere are the two commit commands I would like to see in git:\n\n  commit-index-content [paths...]\n\n    Commits the content of the index for the given paths, (or all\n    paths in the index). The index content can be manipulated with\n    \"git add\", \"git rm\", \"git mv\", and \"git update-index\".\n\n  commit-working-tree-content [paths...]\n\n    Commits the content of the working tree for the given paths, (or\n    all tracked paths). Untracked files can be committed for the first\n    time by specifying their names on the command-line or by using\n    \"git add\" to add them just prior to the commit. Any rename or\n    removal of a tracked file will be detected and committed\n    automatically.\n\nRationale summary\n-----------------\nThese two commands capture a distinct conceptual split that is useful\nfor what users want to do with git. The split is necessary and\nsufficient to provide access to four different useful pieces of commit\nmachinery. This is more functionality than in current git, and is\nprovided with more clarity.\n\nThe semantics of the two commands above are distinct enough that any\ngiven tutorial introduction to git could outline a complete work-flow\nby using only one or the other of the two commands, (or by presenting\none first and then expanding to the other).\n\nThe conceptual split here is necessary. In general, neither of the two\ncommands can be defined in terms of the other. This is independent of\nthe fact that commit-index-content is more core and provides shared\nmachinery for commit-working-tree-content. It is also independent of\nthe fact that commit-working-tree-content _can_ be defined in terms of\ncommit-index-content in the special case of the \"all tracked paths\"\nform.\n\nThe two-way split here is also sufficient. It provides access to four\ndifferent, and useful, pieces of commit machinery. Of the four, only\nthree of these pieces currently exist in git. The new behavior is that\nof \"commit-index-content paths...\"  and is actually quite useful as\ndescribed in the detailed rationale below.\n\nFinally, the two-way split here is simpler and more clear than the\nthree different commit commands currently provided by git, (\"commit\",\n\"commit paths...\", and \"commit -a\"). The improved clarity comes from\ntaking advantage of the following standard command-line convention:\n\n\tIf optional arguments are omitted from a command, the command\n\tis semantically equivalent to some default argument being\n\tprovided.\n\nThis convention is standard across many unix commands and is prevalent\nin git itself, (such as commands like git-log defaulting to HEAD when\nno revision specifier is provided). Note that this convention is not\nfollowed by the current git-commit. The behavior of \"git commit\" and\n\"git commit paths...\" involve distinct semantics. It is not the case\nthat \"git commit\" is equivalent to \"git commit paths...\" with some\ndefault argument supplied. Violating this command-line convention is\nunkind in general, but it also steals \"space\" from the command-line\nfor implementing the semantics of \"git commit\" with the application of\na <paths...> limit. This is discussed in more detail below.\n\nSo, by cleanly separating the two different useful git-commit\nbehaviors, and applying a standard command-line convention, we end up\nwith more functionality and less to teach. What's not to love? All\nthat would be missing is to come up with names for the two\ncommands. As I promised above, I'm going to avoid proposing any\nbinding of the concepts to realistic names here, but I will point out\nthat one of the \"names\" might very well be a command-line option\nalteration of the other command.\n\nRationale details\n-----------------\nAlthough the conceptual split is only two commands, the actual\nimplementation of this functionality breaks down into four separate\ninternal behaviors, (based on whether doing \"given paths\" or \"all\ntracked paths\"). Three of the four exist in git already, while the\nfourth is new, (and also useful). Let's review each of the four along\nwith the names that git currently provides for them:\n\n1. commit-index-content\t\t# all paths in the index\n\n    This functionality currently exists as \"git commit\" and is the\n    oldest and definitely the \"most core\" git commit command. Until\n    fairly recently, all other git commit commands could easily be\n    described as a variation of this functionality.\n\n2. commit-index-content paths...\n\n    This functionality does not currently exist in any git commit\n    command, as far as I know. The behavior is to commit only a\n    (path-based) subset of the content that has been staged into the\n    index.\n\n    I was originally just going to say that this functionality \"might\n    be useful in some cases\", but coincidentally Alan Chandler\n    happened to request it just yesterday on the list:\n\n\tI have been editing a set of files to make a commit, and after editing each\n\tone had done a git update-index.\n\n\tAt this point I am just about to commit when I realise that one of the files\n\thas changes in it that really ought to be a separate commit.\n\n\tSo effectively, I want to do one of three things\n\n\ta) git-commit <that-file>\n\n    It's interesting to note that either of the two solutions\n    suggested in response to Alan might not work in general. For\n    example, \"git reset\", would not be a satisfactory solution if the\n    user had dirty content in any of the affected files compared to\n    what was staged in the index. Similarly, just removing the\n    safety-valve on the existing \"git commit <that-file>\" would commit\n    the wrong content if the working-tree contents of <that-file> were\n    dirty with respect to the index.\n\n    Now, it might still sound far-fetched to imagine wanting to commit\n    a subset of something staged in the index while also having dirty\n    content, but it occurs to me that I would actually _love_ to have\n    this capability. The case I would use it for is fairly common,\n    (and something that I think will speak to Junio who often brings\n    up a similar scenario).\n\n    Here's where I would like this functionality:\n\n\tI receive a patch while I'm in the middle of doing other work,\n\t(but with a clean index compared to HEAD, which is what I've\n\tusually). The patch looks good, so I want to commit it right\n\taway, but I do want to separate it into two or more pieces,\n\t(commonly this is because I want to separate the \"add a test\n\tcase demonstrating a bug\" part from the \"fix the bug\"\n\tpart). So, if I could do:\n\n\tgit apply --index\n\tgit commit-index-content <files that add the test case>\n\tgit commit-index-content\n\n\tThen this would do exactly what I want. I wouldn't even have\n\tto think about whether my local modifications are to any of\n\tthe same paths as touched by the patch.\n\n    Today, in this scenario, what I have to do is to create a\n    temporary branch with a clean working tree, and then use the index\n    to stage the commit there. That process involves a few annoyances,\n    (stashing my dirty work, inventing a free name for the temporary\n    branch (which usually involves \"git branch -D tmp\"), switching back\n    when I'm done, and trying to remember to clean up the branch). The\n    new capability would let me skip _all_ of that overhead and\n    instead I could just delight in the beauty and power of the\n    index. Woo-hoo!\n\n3. commit-working-tree-content\t\t# all tracked files\n\n    This functionality currently exists as \"git commit -a\" and, while\n    not _really_ old in git's history, its invention predates my\n    initial exposure to git. It has almost always been described in\n    terms of its implementation, (\"first update the index for all\n    paths in the index, then commit that index\").\n\n    One benefit of this description is that it forces the user to\n    learn about the index up front, (and gain a better understanding\n    of git's model). One cost is that the user is forced to learn a\n    two-stage implementation for a single-step process, (commit my\n    changes). I won't try to weigh the costs/benefits here, but\n    compare this to the description in (4) below.\n\n4. commit-working-tree-content paths...\n\n    This functionality currently exists as \"git commit paths...\" and\n    is the newest variant of any git-commit command described here.\n\n    I think the evolution of what the semantics of the \"git commit\n    paths...\" command-line has been is very instructive. There was a\n    time when this command could be described in terms of a two-stage\n    manipulation of \"the\" index just like \"commit -a\" is described\n    today. That is:\n\n\tOld: first update the index for all specified paths, then\n\t     commit the index\".\n\n    But then the semantics were changed and the new description does\n    not involve the index at all:\n\n\tNew: Commit only the files specified on the command line.\n\n    The old behavior is still available with the --include option, but\n    nobody has ever come out in favor of that being a useful command,\n    (I agree it is not useful at all). Meanwhile, the new (default)\n    behavior as been strongly identified by Linus as extremely\n    useful. Junio has recently noticed that the old --index behavior\n    is more conceptually consistent with the classic, commit-the-index\n    definition of the core \"git commit\", but that's not sufficient\n    justification for promoting functionality that would never be\n    useful.\n\n    So the evolution of the current \"commit paths...\" shows utility of\n    functionality being a primary concern in defining the semantics of\n    git commands. And that's wonderful.\n\nIn my opinion, what has happened with the evolution of \"commit paths\"\nand \"commit -a\" is that a new conceptual commit behavior has been\ninvented, (what I've termed commit-working-tree-content), but it\nhasn't been recognized yet as separate from the core\ncommit-index-content nature of \"git commit\". And there's some muddling\nin that simply adding a <paths..> argument to \"git commit\" completely\nchanges its semantics, (which violates the command-line convention I\ndescribed above).\n\n-Carl\n"},{"id":"295997","messageId":"87bqmj2zit.wl%cworth@cworth.org","threadId":"43158","inReplyTo":"87d56z32e1.wl%cworth@cworth.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-04T20:10:18Z","receivedAt":"2006-12-04T20:10:18Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"> \tSo, if I could do:\n>\n> \tgit apply --index\n> \tgit commit-index-content <files that add the test case>\n> \tgit commit-index-content\n>\n> \tThen this would do exactly what I want. I wouldn't even have\n> \tto think about whether my local modifications are to any of\n> \tthe same paths as touched by the patch.\n\nBTW, the current \"apply --index\" doesn't allow what I imagined in the\nscenario above. It notices that the affected file is different in the\nworking tree compared to the index and just refuses to do anything.\n\nGiven that safety-valve in git-apply, the current behavior of \"git\ncommit paths\" would allow for splitting a submitted patch into two\ncommits.\n\nThe difference is that it only works if the local modifications do not\naffect any of the same paths as the patch. The user is freed from\nworrying about this somewhat, since if it's not the case, then\ngit-apply just complains and doesn't do anything.\n\nBut what might be very interesting is a modified \"git-apply --index\"\nthat would not fail in this case, but would instead do the following:\n\n\t1. Apply the patch to the working tree\n\n\t2. Apply the patch to the index\n\nAnd of course, if either fails then the entire apply operation fails,\nleaving no changes to working tree or to the index.\n\nWith that new git-apply behavior, then the scenario I outlined above\nwould work, and would work in spite of any changes to the same file in\nboth the working tree and the index. It would also require the\nseparate commands for commit-index-content vs.\ncommit-working-tree-content as described in my original message above.\n\n-Carl\n"},{"id":"296348","messageId":"el239s$e1i$1@sea.gmane.org","threadId":"43158","inReplyTo":"87bqmj2zit.wl%cworth@cworth.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2006-12-04T21:19:55Z","receivedAt":"2006-12-04T21:19:55Z","isPatch":false,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Carl Worth wrote:\n\n> But what might be very interesting is a modified \"git-apply --index\"\n> that would not fail in this case, but would instead do the following:\n> \n>         1. Apply the patch to the working tree\n> \n>         2. Apply the patch to the index\n> \n> And of course, if either fails then the entire apply operation fails,\n> leaving no changes to working tree or to the index.\n\nOr even new option to git-apply, namely --index-only, which would apply\npatch to index only.\n\nBTW. With git-apply we have three possibilities to apply patch to:\nHEAD, index and working tree version, and three possibilities to\nstore result in: working tree only, working tree and index both,\nand index only.\n-- \nJakub Narebski\nWarsaw, Poland\nShadeHawk on #git\n\n"},{"id":"293946","messageId":"87vekr1327.wl%cworth@cworth.org","threadId":"43158","inReplyTo":"el239s$e1i$1@sea.gmane.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-05T02:36:48Z","receivedAt":"2006-12-05T02:36:48Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Mon, 04 Dec 2006 22:19:55 +0100, Jakub Narebski wrote:\n> Or even new option to git-apply, namely --index-only, which would apply\n> patch to index only.\n\nWouldn't that leave me in a state where my working-tree would be all\nset for reverting the patch? Can you imagine a scenario where that\nwould actually be useful?\n\n-Carl\n"},{"id":"296384","messageId":"20061205035123.GA8831@thunk.org","threadId":"43158","inReplyTo":"87d56z32e1.wl%cworth@cworth.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Theodore Tso","fromEmail":"tytso@mit.edu","sentAt":"2006-12-05T03:51:23Z","receivedAt":"2006-12-05T03:51:23Z","isPatch":false,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"On Mon, Dec 04, 2006 at 11:08:22AM -0800, Carl Worth wrote:\n>\n> Here are the two commit commands I would like to see in git:\n> \n>   commit-index-content [paths...]\n> \n>     Commits the content of the index for the given paths, (or all\n>     paths in the index). The index content can be manipulated with\n>     \"git add\", \"git rm\", \"git mv\", and \"git update-index\".\n> \n>   commit-working-tree-content [paths...]\n> \n>     Commits the content of the working tree for the given paths, (or\n>     all tracked paths). Untracked files can be committed for the first\n>     time by specifying their names on the command-line or by using\n>     \"git add\" to add them just prior to the commit. Any rename or\n>     removal of a tracked file will be detected and committed\n>     automatically.\n\nI think this is a very interesting proposal, although I think I\ndisagree with the last part:\n\n      Any [rename or] removal of a tracked file will be detected and\n      committed automatically.\n\nIf adds aren't going done automatically (because otherwise you have\nproblems with foo.c~ accidentally getting checked it), then it's\nnon-symmetric to expect that deletes will also happen automatically.\nIt's relatively rare that files are removed or renamed, and sometimes\nfiles accidentally disappear.  \n\nSo in the case where there are no pathnames given to \"git\ncommit-working-tree-content\", I would argue that it does not do any\nimplicit \"git add\" on new files NOR any implicit \"git rm\" on missing\nfiles unless the user actually specifies an --implicit-add or\n--implicit-delete option, respectively.  If users want to make\n--implicit-add and/or --implicit-delete the default, that could be a\nconfiguration option, but I don't think it should be a default.\n\n\nA second issue which you left unspecified is what should\ncommit-working-tree-content do if the index != HEAD.  In particular,\nin this case:\n\nedit foo.c\ngit update-index\nedit foo.c\ngit commit-working-tree-content foo.c\n\nWhat should happen to foo.c in the index?  Should it be stay the same?\nShould the contents be replaced with version of foo.c that has just\nbeen commited?  The latter seems to make sense, but runs the risk of\nlosing the data (what was in the index).  The former has the downside\nthat the index might have a version of foo.c which is older than what\nhas been just commited, which could be confusing.  Or should git\ncommit-working-tree abort with an error message if index != HEAD?\n\n"},{"id":"298143","messageId":"7virgqj1hh.fsf@assigned-by-dhcp.cox.net","threadId":"43158","inReplyTo":"20061205035123.GA8831@thunk.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-05T06:33:30Z","receivedAt":"2006-12-05T06:33:30Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Theodore Tso <tytso@mit.edu> writes:\n\n> A second issue which you left unspecified is what should\n> commit-working-tree-content do if the index != HEAD.  In particular,\n> in this case:\n>\n> edit foo.c\n> git update-index\n> edit foo.c\n> git commit-working-tree-content foo.c\n>\n> What should happen to foo.c in the index?  Should it be stay the same?\n> Should the contents be replaced with version of foo.c that has just\n> been commited?  The latter seems to make sense, but runs the risk of\n> losing the data (what was in the index).  The former has the downside\n> that the index might have a version of foo.c which is older than what\n> has been just commited, which could be confusing.  Or should git\n> commit-working-tree abort with an error message if index != HEAD?\n\nThat is exactly the \"'commit --only' jumps the index\" issue.\n\nUpdating the index with what is committed makes sense because\nthe commit after this --only commit happens builds on top of it,\nand not doing so would mean the change to foo.c would be\nreverted.  As you mentioned above, updating the index with the\ncommitted version of foo.c means information loss of what was\nstaged earliser, and the traditional behaviour has been to\n\"abort with an error if index != HEAD\" at that path, which was a\nsafety valve.\n\nHowever, In the recent discussion, everybody (Linus, Nico, and I\nincluded) seems to think this information loss is acceptable and\nin fact is even useful.  I've sent a patch to remove the\nobsolete safety valve for comments today, but haven't applied it\nto any of my public branches yet, but most likely I will, and it\nwill happen sooner with encouragement from the list.\n"},{"id":"297857","messageId":"87r6ve26g3.wl%cworth@cworth.org","threadId":"43158","inReplyTo":"20061205035123.GA8831@thunk.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-05T06:38:20Z","receivedAt":"2006-12-05T06:38:20Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Mon, 4 Dec 2006 22:51:23 -0500, Theodore Tso wrote:\n>\n> If adds aren't going done automatically (because otherwise you have\n> problems with foo.c~ accidentally getting checked it), then it's\n> non-symmetric to expect that deletes will also happen automatically.\n> It's relatively rare that files are removed or renamed, and sometimes\n> files accidentally disappear.\n\nIt's non-symmetric, yes, but it's what I would personally like. It's\nnot an essential aspect of the proposal, so it could go either way as\nthe git crowd decides.\n\nTo explain my personal preference, I like the notion of all files\nbeing \"untracked\" until I inform the system about their\nexistence. After that, I'd like the system to take care of them and\nnotice when they get modified, or when they get deleted.\n\n> So in the case where there are no pathnames given to \"git\n> commit-working-tree-content\", I would argue that it does not do any\n> implicit \"git add\" on new files NOR any implicit \"git rm\" on missing\n> files unless the user actually specifies an --implicit-add or\n> --implicit-delete option, respectively.  If users want to make\n> --implicit-add and/or --implicit-delete the default, that could be a\n> configuration option, but I don't think it should be a default.\n\nThe ability to configure --implicit-delete and --implicit-add to\ngit-commit seems good. They're long enough arguments that\n\n> What should happen to foo.c in the index?  Should it be stay the same?\n> Should the contents be replaced with version of foo.c that has just\n> been commited?  The latter seems to make sense, but runs the risk of\n> losing the data (what was in the index).  The former has the downside\n> that the index might have a version of foo.c which is older than what\n> has been just commited, which could be confusing.  Or should git\n> commit-working-tree abort with an error message if index != HEAD?\n\nThis case is already under debate in a separate thread. There \"git\ncommit files\", (which really is commit-working-tree-content already),\ncurrently errors out in this case, but the proposal is to allow it to\nproceed with the commit, (thereby \"losing\" the intermediate staged\ncontent).\n\n-Carl\n\n"},{"id":"297186","messageId":"7vejrdbzdb.fsf@assigned-by-dhcp.cox.net","threadId":"43158","inReplyTo":"87d56z32e1.wl%cworth@cworth.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-06T01:13:20Z","receivedAt":"2006-12-06T01:13:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n>     ... The case I would use it for is fairly common,\n>     (and something that I think will speak to Junio who often brings\n>     up a similar scenario).\n>\n>     Here's where I would like this functionality:\n>\n> \tI receive a patch while I'm in the middle of doing other work,\n> \t(but with a clean index compared to HEAD, which is what I've\n> \tusually). The patch looks good, so I want to commit it right\n> \taway, but I do want to separate it into two or more pieces,\n> \t(commonly this is because I want to separate the \"add a test\n> \tcase demonstrating a bug\" part from the \"fix the bug\"\n> \tpart).\n\n(This is offtopic)\n\nI often faced situations like that during git.git history.  One\npatch to expose the bug in the existing code, and another to fix\nit.  And there are three ways to make that commit.\n\n (1) one commit exposes, then another fixes.\n (2) one commit fixes, then another verifies the bug is no more.\n (3) one commit to include both.\n\nIn my experience, (1) is only useful during the time I am coming\nup with the fix (if I am fixing it myself) or during the time I\nam reviewing and committing the fix (if I am applying somebody\nelse's patch).  Committing in that order lets me validate the\nbrokenness after making the first commit, and then lets me feel\ngood by not seeing that problem after the second commit.  But\nthis means I deliberately record a state that is known not to\npass the test, which means it is a problem for somebody else in\nthe future when the history needs to be bisected to hunt for an\nunrelated bug.  If the \"test\" is just an optional test in the\ntest suite, then it is easy to work around (the person who is\nbisecting can ignore that bug by not running that particular\ntest), but if it is an assert somewhere deep inside the code,\nignoring it is not very easy, especially if the person who is\nbisecting is not familiar with that part of the code.\n\nWhat I recommend people to do these days is either (2) or (3),\nbut do so _after_ verifying the fix in the reverse order.  The\ncriteria to choose between (2) or (3) is fairly simple: if the\n\"test\" is easily separable (e.g. changes to a test script file\nthat does not overlap with the \"fix\" patch), roll both in one\ncommit.  Then it would not later cause problems for bisection.\n\nEnough of offtopic.\n\nThe sequence to split a patch in place would be (I'll speak in\nthe present tense and pretend Nico's \"git add\" does not exist\nyet):\n\n\tgit apply\n        git update-index <files for the first batch>\n        git commit\n        git commit -a ;# the remainder\n\nso you do not necessarily need a new \"concept\".  It is\ninconvenient that you need to deal with new files, but that is a\nminor detail compared to a bigger problem I'll mention in the\nnext paragraph.\n\nI think the problem with your thinking is that you still are\ntalking from \"file boundary matters\" point of view.  The above\nsequence is only useful if the patch to be split is separable\ncleanly at the file boundary, in which case, I would (and I've\ndone so often) split the patch file in my editor and run two\nindependent \"git apply + git commit\" sequences.  That way, I\ncould test each in isolation (perhaps with some dirty working\ntree state if I do not stash them away and do reset --hard).\nAnything more realistic and practically useful would require\nsplitting of the patch in semantic ways regardless of file\nboundaries.\n\nAs I have already said (and you seemed to share the same\ndiscipline), I do not like people committing anything\nnon-trivial that is not tested.  The patch you received might\nnot have been tested by the submitter, but there is a chance\nthat it might have been ;-).  But with the way you said you want\nto make the commits in the message I am responding to, the first\ncommit would never have been tested by anybody in isolation, not\nby the original submitter even if he tested the patch before\ngiving it to you, nor you -- your working tree had either none\nof his patch or all of it, and never was in the state with only\nthe first batch.\n\nSo while at the theoretical level I understand what you would\nwant to achieve with the \"single patch that should have been\nsent as two patch series\" example, from the practical point of\nview I do not see much value in it (because \"file boundary\nmatters\" is a minority case that is not very interesting), and\nfrom the discipline point of view I would rather not want to\nhave such a too-convenient way to commit things that were\ndifferent in nontrivial ways from what you had in your working\ntree (if we use something like Darcs record to update\nhunk-by-hunk).\n\n>     The old behavior is still available with the --include option, but\n>     nobody has ever come out in favor of that being a useful command,\n\nThat is a slight overstatement.  When committing with paths\nargument to conclude a merge, --include semantics is the only\nvariant that makes sense (--only semantics is so wrong that\nthere is a safety valve that catches it).  Most of the time,\nhowever, if I need to resolve and record a complicated merge, I\nwould either do \"update-index\" to clear the deck of the paths\nthat I already dealt with, and by the time I would type \"git\ncommit\", I have an index that has exactly what I want in the\nmerge commit.  That makes --include a less often used form.  If\na merge is small and easy to resolve at only a few paths, it\nstill is handy to say \"git commit -i resolved-path.c\".  It does\nnot add anything to the semantics -- it is only a typesaver.\n\n"},{"id":"296882","messageId":"874ps91v79.wl%cworth@cworth.org","threadId":"43158","inReplyTo":"7vejrdbzdb.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-06T04:53:30Z","receivedAt":"2006-12-06T04:53:30Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 05 Dec 2006 17:13:20 -0800, Junio C Hamano wrote:\n> (This is offtopic)\n\nIt's an interesting topic nonetheless, so I'll comment anyway.\n\n>  (1) one commit exposes, then another fixes.\n>  (2) one commit fixes, then another verifies the bug is no more.\n>  (3) one commit to include both.\n\nI feel very strongly that I want (1) in the history.\n\n> unrelated bug.  If the \"test\" is just an optional test in the\n> test suite, then it is easy to work around (the person who is\n> bisecting can ignore that bug by not running that particular\n> test), but if it is an assert somewhere deep inside the code,\n> ignoring it is not very easy, especially if the person who is\n> bisecting is not familiar with that part of the code.\n\nGranted, something like an assert that breaks the library would not be\na useful thing to have in the history. I'm certainly not in favor of\nsomething like that.\n\nI'm talking about tests that demonstrate pre-existing broken-ness in\nthe code. In the case of cairo, our test suite is entirely optional,\nand each test is out-of-process, so even if a test totally crashes the\nsuite continues and it's easy to ignore that.\n\nBut it's not just the correctness test suite. We also have a\nperformance test suite, and I encourage the same \"add test case, then\nperformance fix\" pattern there. This shows an even more obvious\nexample of why it's useful to have separate commits in the history,\n(since someone may want to verify the performance impact on a separate\nsystem at any point in the future, and the two commits makes it easy\nto get \"before\" and \"after\" for the performance fix results from the\nnew test case).\n\n> The sequence to split a patch in place would be (I'll speak in\n> the present tense and pretend Nico's \"git add\" does not exist\n> yet):\n>\n> \tgit apply\n>         git update-index <files for the first batch>\n>         git commit\n>         git commit -a ;# the remainder\n\nYes, I can use this today, and I do, (as I mentioned in my mail). The\nonly requirement is that I start with a non-dirty working tree. I can\narrange that, but it would be just a bit less inconvenient if I didn't\nhave to.\n\n> so you do not necessarily need a new \"concept\".\n\nNo, I don't need it. And this \"commit-index-content [paths...]\" was\nthe least significant part of my proposal. As I said, originally I was\njust going to say this \"might be useful in some cases\", but then\nsomeone just happened to request this feature on the list at the same\ntime I was considering the proposal.\n\nAnyway, it spite of this being an accidental feature of y proposal, it\nseems to be the only part you commented on. Even if this functionality\nweren't made available at all, I'd still be interested in your\ncomments on the main thrust of my proposal. I think that consists of:\n\n\t1. Unifying the two current commands that provide\n\t   commit-working-tree-content semantics into a single,\n\t   use-oriented description.\n\n\t2. Avoiding a change of semantics triggered by merely applying\n\t   pathname arguments without any command-line option or\n\t   alternate command name.\n\n> As I have already said (and you seemed to share the same\n> discipline), I do not like people committing anything\n> non-trivial that is not tested.\n\nIndeed. I like that discipline very much. And in fact, that's an\nimportant reason that I split a patch that I receive like this, (or\njust bounce it, which I often do, and would definitely do if it's not\neasy to split)\n\n>                                 But with the way you said you want\n> to make the commits in the message I am responding to, the first\n> commit would never have been tested by anybody in isolation, not\n> by the original submitter even if he tested the patch before\n> giving it to you, nor you -- your working tree had either none\n> of his patch or all of it, and never was in the state with only\n> the first batch.\n\nWho said I wouldn't test it? I do split commits like this precisely so\nthat I _can_ test it this way---and git helps a lot here. I do the\nsplit commit, then easily back up to the revision that adds the test\ncase, verify the test fails before the bug fix, (which is something\nthe maintainer doesn't get a chance to do with your (2) approach),\nthen move forward and verify that the test passes after the fix.\n\nSo, sure, I haven't ever had that working tree before the commit. But\ngit makes it easy to get that working tree after I commit and test\neverything before I push anything out.\n\n[Incidentally, that's yet _another_ thing people can mention to\nfriends who come from cvs and think that the separation of commit and\npush is annoying. And that's in addition to all of the performance\nadvantages, the ability to work entirely offline, etc. etc.]\n\n> >     The old behavior is still available with the --include option, but\n> >     nobody has ever come out in favor of that being a useful command,\n>\n> That is a slight overstatement.\n\nOK. I should have worded that as \"I wasn't aware of any arguments...\".\n\n>                That makes --include a less often used form.  If\n> a merge is small and easy to resolve at only a few paths, it\n> still is handy to say \"git commit -i resolved-path.c\".  It does\n> not add anything to the semantics -- it is only a typesaver.\n\nOh, OK. I see it now. That's for combining the update-index, (or\n\"resolve/resolved\"---is there any consensus on that being a useful\nsynonym for update-index here?) and the commit into a single\ncommand. I guess that's just a shortcut I've never used.\n\nSo, yes, that shortcut would not fit cleanly into either of my\nproposed commit-working-tree-content nor commit-index-content. That\nwould still require a two-stage:\n\n\tgit update-index resolved-path.c\n\tgit commit-index-content\n\n-Carl\n"},{"id":"297940","messageId":"Pine.LNX.4.63.0612061052490.28348@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"43158","inReplyTo":"874ps91v79.wl%cworth@cworth.org","subject":"Commit order in git.git, was Re: [RFC] Two conceptually distinct commit commands","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2006-12-06T09:54:24Z","receivedAt":"2006-12-06T09:54:24Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Tue, 5 Dec 2006, Carl Worth wrote:\n\n> On Tue, 05 Dec 2006 17:13:20 -0800, Junio C Hamano wrote:\n> > (This is offtopic)\n> \n> It's an interesting topic nonetheless, so I'll comment anyway.\n> \n> >  (1) one commit exposes, then another fixes.\n> >  (2) one commit fixes, then another verifies the bug is no more.\n> >  (3) one commit to include both.\n> \n> I feel very strongly that I want (1) in the history.\n\nNote that (1) maybe would reflect history better, but (2) and (3) are way \nnicer to bisecting.\n\nI fell very strongly that I want (3) in the history.\n\n(Though I am guilty of many instances of (2)...)\n\nCiao,\nDscho\n"},{"id":"295066","messageId":"873b7t0zo8.wl%cworth@cworth.org","threadId":"43158","inReplyTo":"874ps91v79.wl%cworth@cworth.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-06T16:14:31Z","receivedAt":"2006-12-06T16:14:31Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Tue, 05 Dec 2006 20:53:30 -0800, Carl Worth wrote:\n> On Tue, 05 Dec 2006 17:13:20 -0800, Junio C Hamano wrote:\n> \t2. Avoiding a change of semantics triggered by merely applying\n> \t   pathname arguments without any command-line option or\n> \t   alternate command name.\n\nBy the way, the original command-line convention I used in the\nproposal was that the omission of an optional argument should be\nequivalent to supplying some default argument. Here's another\nconvention that is also useful to examine:\n\n\tAdding path-name arguments limits the behavior of the command,\n\t(and does not otherwise change the semantics).\n\nI don't know that this is as universal a convention outside of git,\nbut it's quite strong within git. The path name limiting exists in\ndeep parts of the machinery and allows for things like:\n\n\tgit log -- paths...\t# path-limited version of \"git log\"\n\tgit diff -- paths...\t# path-limited version of \"git diff\"\n\tetc.\n\nIt's interesting to look at how the various commit commands fit (or\ndo not fit) this convention:\n\n  git commit paths...\n  git commit --only paths...\n\n\tThis command cannot be explained in terms of the semantics of\n\t\"git commit\" (without command-line options). This command\n\t_can_ be explained as a path-limited version of \"git commit -a\".\n\n  git commit --include paths...\n\n\tThis command does something _extra_ to the given paths before\n\texecuting the equivalent of \"git commit\". I think this is a\n\tfairly unique violation of the path-limiting convention.\n\nThe proposal I made with commit-working-tree-content and\ncommit-index-content consistently follow the path-limiting convention.\n\nI think consistency of command-line conventions like this are\nimportant for making the tool usable. And there have been notable\nimprovements to consistency of convention in git recently, (for\nexample, using <since>..[<until>] in git-format-patch rather than\n<his> <mine>).\n\n-Carl\n"},{"id":"296553","messageId":"7virgo511i.fsf@assigned-by-dhcp.cox.net","threadId":"43158","inReplyTo":"874ps91v79.wl%cworth@cworth.org","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2006-12-06T18:31:21Z","receivedAt":"2006-12-06T18:31:21Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Carl Worth <cworth@cworth.org> writes:\n\n> ... Even if this functionality\n> weren't made available at all, I'd still be interested in your\n> comments on the main thrust of my proposal. I think that consists of:\n>\n> \t1. Unifying the two current commands that provide\n> \t   commit-working-tree-content semantics into a single,\n> \t   use-oriented description.\n>\n> \t2. Avoiding a change of semantics triggered by merely applying\n> \t   pathname arguments without any command-line option or\n> \t   alternate command name.\n\nI am not sure what needs to be commented on at this point, since\nit is not yet clear to me where you want your proposal to lead\nus.\n\nI do not agree with your \"three commands\" or \"two semantics\"\ncharacterization of the current way \"git commit\" works.  \"git\ncommit\" without any optional argument already acts as if a\nsensible default arguments are given, that is \"no funny business\nwith additional paths, commit just what the user has staged\nalready.\"\n\n\"git commit\" is primarily about committing what has been staged\nin the index, and \"--all\" is just a type-saver short-hand (just\nlike \"--include\" is) to perform update-index the last minute and\nnothing more.  In other words, \"--all\" is a variant of the\npathname-less form \"git commit\".  It is not a variant of \"git\ncommit --only paths...\" form, as you characterized.\n\nThe pathname form (the \"--only\" variant) on the surface seem to\nwork differently, but when you think about it, it is not all\nthat different from the normal commit.  We explain that it\nignores index, but in the bigger picture, it does not really.\n\nIn this sequence:\n\n\tedit a b\n\tgit update-index a\n\tgit commit --only b\n\tgit commit --all\n\nthe first commit does \"jump\" the changes already made to the\nindex, but after it makes the commit, the index has the same\ncontents as if you did \"git update-index a b\" where you ran that\n\"git commit\".  In other words, it is just a handy short-hand to\npretend as if you did the above sequence in this order instead:\n\n\tedit a b\n        git update-index b\n        git commit\n        git update-index a\n        git commit\n\nSo I actually think it is a mistake to stress the fact that \"git\ncommit --only paths...\" seems to act differently from the normal\n\"git commit\" too much.  It just helps to split the changes in\nyour working tree if the changes happen to be cleanly separable\nat file boundaries (aka \"CVS mentality\").  When the changes are\nnot cleanly separable at file boundaries, the \"more painfully\nindex aware\" variant also allows you to split the changes in\nyour working tree in the time dimension:\n\n        edit a\n\tgit update-index a\n        edit a\n        git commit ;# without paths\n\tgit update-index a\n        git commit\n\nIn short, while I understand that your \"proposal\" shows your own\nway to summarize the semantics of \"git commit\", I am not seeing\nwhat it buys us, and I do not see the need to come up with a\npair of new two commands for making commits (if that is what the\nproposal is about, that is, but it is not clear to me if that is\nwhat you are driving at).  I think it would only confuse users.\n\n> \tI receive a patch while I'm in the middle of doing other work,\n> \t(but with a clean index compared to HEAD, which is what I've\n> \tusually). The patch looks good, so I want to commit it right\n> \taway, but I do want to separate it into two or more pieces,\n> \t(commonly this is because I want to separate the \"add a test\n> \tcase demonstrating a bug\" part from the \"fix the bug\"\n> \tpart).\n> ...\n> Who said I wouldn't test it? I do split commits like this precisely so\n> that I _can_ test it this way---and git helps a lot here. I do the\n> split commit, then easily back up to the revision that adds the test\n> case, verify the test fails before the bug fix, (which is something\n> the maintainer doesn't get a chance to do with your (2) approach),\n> then move forward and verify that the test passes after the fix.\n>\n> So, sure, I haven't ever had that working tree before the commit. But\n> git makes it easy to get that working tree after I commit and test\n> everything before I push anything out.\n\nYou saw a good patch in the middle of something that you did not\nwant to lose your working tree changes for.  That good patch was\nnot really good enough to be applied straight into your tree but\nneeded tweaking and splitting.  Nevertheless you went ahead and\nmade two commits out of that patch, even though you were in the\nmiddle of something.  You could not test them right away after\ncommitting because your tree was in no shape to test them in\nisolation.  But that is excusable because you would not push\nthese commits out right away, before you have a chance to test\nthem by rewinding your working tree when you are done with what\nyou were originally doing.\n\nIs it just me who finds the above a very much made-up example?\n\nIt means the patch (which is good and not good at the same time)\nwas not all that urgent after all, and it could well have waited\nuntil you are done with what you were originally doing.\n\nIn any case, I should clarify my aversion to partial commits a\nbit.  What is more important is to notice that, while you cannot\ncompile-and-run test what is in the index in isolation (without\na fuse that exports the index contents as a virtual filesystem\n-- anybody interested?), you _can_ preview and verify the text\nthat is going to be committed by comparing the index and the\nHEAD.  And for that, your \"staging\" action (i.e. Nico's \"git\nadd\") needs to be a separate step from your \"committing\" action.\n\nIn other words, I would even love Johannes's \"per hunk commit\"\nidea, at least if it had an option to preview the whole thing\njust one more time before committing, and I would love it better\nif it had an option for not committing but just updating.  You\ncould:\n\n\t$ edit foo bar\n\t: the whole mess in working tree is in no shape to be committed.\n        $ git add foo\t;# stage the state of the entire file\n        $ git hunk-add bar ;# go interactive and update index selectively\n\t$ git status -v\t;# that is \"git commit --dry-run --diff\"\n\nto review what would be committed.  So while the commit that\nwould be made may not be compile-and-run tested, I would not\nmind partial commit that much (and after all not all the\nprojects that track their contents with git are not \"compiled\"\nnor \"need testing\" projects -- they could be tracking plain text\ndocumentation, and the last-minute eyeballing may be a good\nenough test for such contents).\n"},{"id":"295731","messageId":"87zma0zjq8.wl%cworth@cworth.org","threadId":"43158","inReplyTo":"7virgo511i.fsf@assigned-by-dhcp.cox.net","subject":"Re: [RFC] Two conceptually distinct commit commands","fromName":"Carl Worth","fromEmail":"cworth@cworth.org","sentAt":"2006-12-06T23:29:35Z","receivedAt":"2006-12-06T23:29:35Z","isPatch":false,"sender":{"key":"cworth@cworth.org","avatar":"https://gravatar.com/avatar/3746dc28cde609bdbd7f939058356e7e2bbd16d21e32274df0725eb3d998bc5b?d=mp&s=160"},"body":"On Wed, 06 Dec 2006 10:31:21 -0800, Junio C Hamano wrote:\n> I am not sure what needs to be commented on at this point, since\n> it is not yet clear to me where you want your proposal to lead\n> us.\n\nThanks for the comments you made here---that's the kind of thing I was\nlooking for.\n\nAs for where I'm trying to lead us, what I really want to do is to\nhelp improve the learnability of git. A big part of that is about\nimproving the set of \"use-oriented\" documentation, (which describes\nhow to achieve tasks, as opposed to what might be termed \"technically\noriented\" documentation which describes how individual tools work). I\nthink too much of the existing documentation falls into the second\nclass.\n\nA parallel thread is already talking about some of the important\norganizational aspects of use-oriented documentation. And I agree with\nthat thread is that the short \"attention span\" is a primary\nconsideration for this kind of documentation. The user has a task to\nbe accomplish, and any text or concepts that aren't contributing to\nthe solution of that task should be eliminated.\n\nNote that when I talk about eliminating unnecessary concepts, I do not\nmean lying to the user about the underlying model or any concepts. We\ncan't have a sugar-coated tutorial that says one thing, and then\nexpect users to \"unlearn\" that if they go deeper into the reference\nmanual. That's a recipe for disaster.\n\nAlso, when I say \"use-oriented\" I'm not suggesting that the\ndocumentation be shallow. It can go as deep as any workflow we care to\ndocument and introduce whatever concepts of git are necessary to\nsupport that workflow. (There is, though a level at which \"technically\noriented\" documentation is all that's needed, or even desired, and\nthat's when the documentation is targeting authors of interfaces that\nbuild on top of git---not users trying to use git to get work done at\nthe command line).\n\nOK, so if my concern is all about documentation, then what am I doing\nproposing new commands or new ways of thinking about existing commands\nrather than just sending documentation patches? The problem is that\nthe current semantics of the following variations of \"git commit\":\n\n\tgit commit\n\tgit commit -a\n\tgit commit paths...\n\ndefeat the goal of writing good, clean use-oriented documentation. So\nthere's some adjustment that should be made first. And I don't even\ncare what the adjustment is, (for example, it doesn't have to be\n\"commit -a by default\"), but please recognize the problem and help me\ncome up with an acceptable way to fix it.\n\nTo demonstrate, let's take the simplest of use cases and try to\ndocument it in as clear a way as possible. Let's imagine we're in a\ntutorial where we've just guided the user to making modifications to\nseveral existing, tracked files, (starting from an initial clone, not\nan init-db), and the next task to teach the user commit for the first\ntime. We would like to document both \"commit a single modified file\"\nand \"commit all modified files\". Here are two approaches that I can\ncome up with:\n\n1. Any commit involves first \"add\"ing together new content, and then\n   committing the result. For example to commit a single file:\n\n\tgit add file\t\t# add new content from file\n\tgit commit\t\t# commit the result\n\n   As a shortcut, \"commit -a\", (or --all) can be used to automatically\n   \"add\" the content of all tracked files before the commit. So the\n   common case of committing all tracked files is as easy as:\n\n\tgit commit -a\t\t# commit content of all tracked files\n\n2. The new content of modified files can be committed by naming the\n   files on the \"git commit\" command line. For example:\n\n\tgit commit file\t\t# commit new content of file\n\n   As a shortcut, \"commit -a\", (or --all) can be used to commit the\n   content of all tracked files:\n\n\tgit commit -a\t\t# commit content of all tracked files\n\nNeither of the above is totally satisfactory.\n\nIn (1) the user is not presented with a framework that will make sense\nof \"git commit files...\". The expansion of \"-a\" as \"--all\" could\neasily give the user the impression that \"git commit files...\" is a\nshortcut for \"git add files...; git commit\", but that's wrong and\ncould lead to unexpected results and confusion.\n\nIn (2) the user is not presented with a framework that will make sense\nof \"git commit\" with no arguments. The user is left to wonder about\nwhy the --all is needed and what it means exactly, (particularly since\n\"git commit\" also commits the content of all tracked files.\n\nVarious fixes have been proposed for these potential confusions. For\nexample, making \"git commit files...\" default to the behavior of\n--include instead of --only would eliminate the confusion I described\nfor (1). And making -a the default for \"git commit\" would eliminate\nthe confusion I described for (2).\n\nHowever, actually implementing either of those fixes would then break\nthe initial \"commit one file\" example from the other approach. Because\nof that, the conversation has often fallen into debate over whether\n(1) or (2) is the \"one true way\" to describe git, and which one leads\nthe user to have an incorrect mental model.\n\nBut I think that debate is misguided since both descriptions are\nworthwhile and valid. (1) is based around an explanation of what \"git\ncommit\" does, and (2) is based around an explanation of what \"git\ncommit files...\" does. And both of these commands are very useful\nexactly how they are.\n\nIt's almost coincidental that \"commit -a\" fits in logically with\neither description.\n\nSo what I was trying to get across in this latest thread is that git's\ncommand-line interface already has two slightly different models for\nwhat's going on in a commit. You don't agree with me on that point\nyet, (more on that below in my reply).\n\nI really don't care what the final fix is, but I would love to see\ndocumentation with no more complexity than the above that accurately\ncaptures the useful functionality.\n\nAnd I don't actually have a concrete proposal for a fix yet---I was\njust offering the commit-index-content and commit-working-tree-content\nideas as ways to think about the issue. Maybe the two documentation\nblurbs above capture it in a better way.\n\nDo you feel like you have a better understanding of what I'm trying to\ndo now?\n\n> I do not agree with your \"three commands\" or \"two semantics\"\n> characterization of the current way \"git commit\" works.  \"git\n> commit\" without any optional argument already acts as if a\n> sensible default arguments are given, that is \"no funny business\n> with additional paths, commit just what the user has staged\n> already.\"\n\nI agree that \"git commit\" does nothing funny by default. What I was\npointing out is that \"git commit\" and \"git commit paths...\" do not\nhave the same semantics. There's really nothing to debate about\nthere. There is no argument you can substitute for <paths...> to give\nyou identical behavior as \"git commit\". That's a fact.\n\n> \"git commit\" is primarily about committing what has been staged\n> in the index, and \"--all\" is just a type-saver short-hand (just\n> like \"--include\" is) to perform update-index the last minute and\n> nothing more.  In other words, \"--all\" is a variant of the\n> pathname-less form \"git commit\".  It is not a variant of \"git\n> commit --only paths...\" form, as you characterized.\n\nI hope the documentation blurbs (1) and (2) above show how \"commit -a\"\ncan be seen as a variant of either \"commit\" or \"commit files...\",\n(which themselves are both useful semantics, but demonstrably\ndistinct).\n\n> The pathname form (the \"--only\" variant) on the surface seem to\n> work differently, but when you think about it, it is not all\n> that different from the normal commit.  We explain that it\n> ignores index, but in the bigger picture, it does not really.\n\nNo, it really is different.\n\n> the first commit does \"jump\" the changes already made to the\n> index, but after it makes the commit, the index has the same\n> contents as if you did \"git update-index a b\" where you ran that\n> \"git commit\".  In other words, it is just a handy short-hand to\n> pretend as if you did the above sequence in this order instead:\n\nHow could you document \"git commit files...\" as a shorthand? A\nshorthand for what exactly? A shorthand for pretending you didn't just\ntype the commands you did type that got the index into its current\nstate, but had instead typed different commands before the commit and\nother commands afterwards?\n\nThat's crazy. That's not a shorthand. That's just plain different\nsemantics. The current \"git commit files...\" command never does commit\nthe contents of \"the\" index as a concept presented by \"git\ncommit\". (This is independent of the fact that the implementation of\n\"git commit files...\" certainly does use an index file somewhere and\nuses it to create a commit object in the same way that \"git commit\"\nuses \"the\" index).\n\n> So I actually think it is a mistake to stress the fact that \"git\n> commit --only paths...\" seems to act differently from the normal\n> \"git commit\" too much.\n\nI think that would be lying to the users and setting them up to get\nconfused later. I discussed this above as the confusion that can\nresult with the explanation of (1). If you teach \"git commit\" as\ncommiting \"the\" index, and de-emphasize that \"git commit files...\"\nis semantically distinct, then how is a user ever supposed to learn\nwhat it is that \"git commit files...\" is actually doing?\n\n> In short, while I understand that your \"proposal\" shows your own\n> way to summarize the semantics of \"git commit\", I am not seeing\n> what it buys us, and I do not see the need to come up with a\n> pair of new two commands for making commits (if that is what the\n> proposal is about, that is, but it is not clear to me if that is\n> what you are driving at).  I think it would only confuse users.\n\nForgive me again for being obtuse. I don't think we should necessarily\nadd two new commands. I was trying to illustrate a problem in the\nexisting command set, and propose a new way of thinking about the\ntasks that the current commands help a user to perform, (committing\ncontent from the working tree or committing content from the index). I\ndon't actually have a concrete proposal for how to take that way of\nthinking and map it to a command set, (and one that would disrupt\ncurrent git users as little as possible). I'd love to have some help\nwith that part.\n\n> Is it just me who finds the above a very much made-up example?\n\nFine. We can ignore that example.\n\n> In any case, I should clarify my aversion to partial commits a\n> bit.  What is more important is to notice that, while you cannot\n> compile-and-run test what is in the index in isolation (without\n> a fuse that exports the index contents as a virtual filesystem\n> -- anybody interested?), you _can_ preview and verify the text\n> that is going to be committed by comparing the index and the\n> HEAD.  And for that, your \"staging\" action (i.e. Nico's \"git\n> add\") needs to be a separate step from your \"committing\" action.\n\nYes, I often use the index as a place to preview things. And it is\ntrue that I find myself using update-index when I could have used\n\"commit paths...\" precisely because I can preview it once more. But I\ndo use the \"commit paths...\" form at times as well. If I have just\nreviewed things in \"git diff\" and there are _really_ obviously\nseparable pieces I will commit them alone with staging into the index\nand reviewing again.\n\nIt's probably the case that I skip the explicit staging and extra\npreview when I can use a single pathname as the argument to \"git\ncommit\".\n\n> In other words, I would even love Johannes's \"per hunk commit\"\n> idea, at least if it had an option to preview the whole thing\n> just one more time before committing, and I would love it better\n> if it had an option for not committing but just updating.\n\nYes! I've wanted tools to help with per-hunk separation before, but\nsince I'm so likely to make mistakes while doing that I would only\nwant that to go into the index so that I could review it before\ncommitting. I guess I might need a per-hunk way to fix up my mistakes\ntoo if I put a hunk into the index that I didn't want to be there.\n\n-Carl\n"}]}