Command-line interface thoughts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]