Quick list of recommendations: 1. Pick aliases for the next commit and the working tree that act like commits on the command-line. 2. Adopt a (semi-)formal notation for describing what commands do. 3. Move the operations "checkout -- <file>" and "reset -- <file>" to their own command names 4. Deemphasize the "branch" command for creating branches. A "normal" (long) email follows. At the end are examples of commands in a not-quite-so-formal notation. I AM NOT ON THE MAILING LIST - PLEASE CC ME ON REPLIES. ------------ I was the primary designer of the PAR2 open file format and write a lot of big software (application-layer multicast, etc.). I've been using Git for 2 months. I love it and I greatly admire the plumbing. However, the default "porcelain" has at times been more confusing than enlightening. I had some ideas about the porcelain and decided they were worth sending to the mailing list. I ran the ideas by the two Git gurus who answer my questions and they agreed with them. I wish I had the time to implement them but I did PAR2 when I had time off and I'm working now. I apologize if any of these are repeats or have already been discussed to death. My recommendations are: 1. Pick aliases for the next commit and the working tree that act like commits on the command-line. By "next commit", I mean "the commit that would be generated if the "commit" command was run right now". "Next commit" is not the same as the index. The index is a _file_ that serves multiple purposes. (Think of it's state during a conflicted merge.) But the index does usually hold the files that change between HEAD and the next commit. For the alias for the next commit and working tree, I suggest "NEXT" and "WTREE". Creating these aliases will make the interface more regular. It will remove oddities like "diff --cached FOO" and replace them with "diff NEXT FOO" and mean that "diff" and "diff FOO" can be explained as "diff WTREE NEXT" and "diff WTREE FOO". 2. Adopt a notation for describing what commands do. I am sure in developer discussions there are descriptions of the "commit" command as something like: HEAD = new(HEAD + (NEXT-HEAD)) NEXT = HEAD Where "-" creates a patch between versions and + applys a patch. Git already has some operators like "^", which refers to the parent of a commit. Those are useful for defining things like "commit --amend": HEAD = new(HEAD^ + (NEXT-HEAD^)) NEXT = HEAD Having this notation and using it in the man pages will make the exact nature of the operation clear. (Right now, it takes a lot of reading to figure out what happens to NEXT with the various command-line options of "reset".) Currently, to understand what commands do, I use "A Visual Git Reference", which has been extremely valuable to me. Kuddos to Mark Lodato for it. http://marklodato.github.com/visual-git-guide/index-en.html [I've included git commands in a not-formal-enough notation at the end of this email.] 3. Move the operations "checkout -- <file>" and "reset -- <file>" to their own command names This is my biggest and most important suggestion. "checkout -- foo.txt" copies foo.txt from NEXT to WTREE. Similarly, "reset -- foo.txt" will copy foo.txt from HEAD to NEXT. These are operations to designate/undesignate files in the next commit and should be grouped with others like them: "add", "rm" and "mv". (In fact, the man page for "reset -- <file>" even says that it is the opposite of "add"!) When these file-based operations are removed from "checkout" and "reset", the purposes of those commands becomes clearer: "checkout" changes HEAD to a new branch and "reset" moves the current branch pointer to a different commit. These operations may share code with the operations "checkout -- <file>" and "reset -- <file>", but they serve different purposes from the user's perspective and the user should have different names to refer to them. As for naming these new commands, the "yet-another-porcelain" renames "reset -- <file>" to "unadd", which I like very much. For the other, my best suggestion is "head-to-next", but I'm sure someone can do better. 4. Deemphasize the "branch" command for creating branches. I assumed that the command "branch" was used for creating branches. After all, that's how it is done in the "gittutorial(7)" man page. However, after reviewing all the major commands, I find that it is the _last_ way I want to create a branch. It creates a new branch, but it doesn't switch HEAD to the new branch! The commands that should be emphasized are "checkout -b <name>", "commit -b <name>", and "stash branch". These make sense in normal git usage. The "branch" command has its uses but it is not usually the way you want to create a branch. These are my suggestions. I wish i had time to implement them, but I'm glad to help in the discussion of them. I'm not on the mailing list, so PLEASE CC ME WITH ANY REPLIES. Michael Nahas ---- These are just some commands written in a not-quite-formal notation. This notation doesn't handle a detached head, adding directories, the state after a conflicted "stash pop", etc. Still, as it is, I think it's very informative to users for getting the gist of what command does. "add foo.txt" NEXT:foo.txt = WTREE:foo.txt "rm foo.txt" delete(NEXT:foo.txt) delete(WTREE:foo.txt) "rm --cached foo.txt" delete(NEXT:foo.txt) "/bin/rm foo.txt" delete(WTREE:foo.txt) "mv foo.txt bar.txt" WTREE:bar.txt = WTREE:foo.txt NEXT.bar.txt = WTREE:foo.txt delete(WTREE:foo.txt) delete(NEXT:foo.txt) "checkout -- foo.txt" WTREE:foo.txt = NEXT:foo.txt "reset -- foo.txt" NEXT:foo.txt = HEAD:foo.txt "commit" HEAD = new(HEAD + (NEXT-HEAD)) NEXT = HEAD "commit --amend" HEAD = new(HEAD^ + (NEXT-HEAD^)) NEXT = HEAD "checkout FOO" (prequires WTREE==NEXT==HEAD) WTREE = FOO NEXT = FOO HEAD ::= FOO // changes the alias of HEAD to refer to FOO "reset --soft FOO" HEAD = FOO // move branch; don't change alias "reset --mixed FOO" (the default) NEXT = FOO HEAD = FOO // move branch; don't change alias "reset --hard FOO" WTREE = FOO NEXT = FOO HEAD = FOO // move branch; don't change alias "stash save" STASH = new(new(HEAD+(NEXT-HEAD))+WTREE-NEXT) NEXT = HEAD WTREE = HEAD push(STASH) "stash pop" STASH = pop() WTREE = HEAD + (STASH-STASH^^) NEXT = HEAD + (STASH^-STASH^^) "branch FOO" FOO = HEAD "commit -b FOO" FOO = new(HEAD + (NEXT-HEAD)) NEXT = FOO HEAD ::= FOO // change alias "checkout -b FOO" (prequires WTREE==NEXT==HEAD) FOO = HEAD // create FOO and make it a copy of HEAD WTREE = FOO NEXT = FOO HEAD ::= FOO // change alias "stash branch FOO" STASH = pop() FOO = STASH^^ // create FOO and make it a copy of STASH^^ NEXT = STASH^ WTREE = STASH HEAD ::= FOO // change alias "merge FOO" (prequires NEXT=HEAD) [ANC is the nearest common ancestor] WTREE = ANC + (WTREE - ANC) + (FOO-ANC) NEXT = ANC + (HEAD - ANC) + (FOO-ANC) HEAD = new(HEAD + (NEXT-HEAD)) NEXT = HEAD "cherry-pick FOO" (prequires WTREE==NEXT==HEAD) HEAD = new(HEAD + (FOO - FOO^)) NEXT = HEAD WTREE = HEAD "rebase FOO" is basically a iterated application of "cherry-pick" -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html