Re: Considering teaching plumbing to users harmful

Previous thread: Re: [PATCH 0/5] add pack index v2 reading capability to git v1.4.4.4 by Junio C Hamano on Wednesday, July 16, 2008 - 10:04 am. (1 message)

Next thread: Hacks for AIX by Chris Cowan on Wednesday, July 16, 2008 - 10:57 am. (7 messages)
From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 10:21 am

Hi,

there have been a number of occasions where I came across people trying to 
be helpful and teaching Git newbies a few tricks.

However, in quite a number of cases, which seem to surge over the last 
weeks, I see people suggesting the use of rev-parse, ls-tree, rev-list 
etc.

Their rationale is invariably "but I found it useful", and they seem to be 
unable to recognize the puzzlement in the faces of the people they are 
trying to help.

Instead they insist that they did nothing wrong.

I had the pleasure of introducing Git to a few users in the last months 
and in my opinion, restricting myself to teaching them these commands 
first helped tremendously:

- clone, pull, status, add, commit, push, log

All of these were presented without options, to keep things simple.

In particular, I refrained from giving them the "-a" option to commit.  
That seemed to help incredibly with their embracing the index as a natural 
concept (which it is).

Often I presented the "pull" and "push" commands _only_ with "origin 
master" ("origin is where the repository came from, and master is the 
branch; you will want to use other parameters here after you used Git for 
a while").

_After_ they grew comfortable with Git, I taught them a few options here 
and there, not hiding, but also not promoting the full range of options.

So the next tricks were

- log -p, rm, diff, diff --cached, show

The last one is "show", and with that command, I taught the 
"<commit>:" and "<commit>:<file>" syntax, too (which some Git old-timers 
did not know about ;-)

The pace needed to be adjusted to the users, in my experience, but not the 
order.

Now, it makes me really, really sad that Git has a reputation of being 
complicated, but I regularly hear from _my_ users that they do not 
understand how that came about.

Am I the only one who deems teaching plumbing to users ("I like it raw!  
So I teach it the same way!") harmful?

Ciao,
Dscho "who is sad"

--

From: Avery Pennarun
Date: Wednesday, July 16, 2008 - 10:53 am

I believe the only way you can get away with such a simple learning
sequence is if your workflow is as simple as that you seem to
describe: everyone has push access to the central 'master'.

That works (and mostly just as well as any other "supposedly easy"
VCS, like svn), but because git's power is so tempting, almost
nobody's real-life repository actually works like that.

At the very least, there will be branches.  And where there are
branches, there's merging.  And with merging comes merge conflicts.
And with merge conflicts comes the crazy (yes, very useful, but still
crazy) conflicted index features.  And so you suddenly need to find
out about things like

       git diff :{1,3}:path/to/filename

Which is a great command, but svn definitely makes it easier to do the
same thing.

Even if you have a repo with widespread push access, git's log looks
annoying compared to svn because of all the merge commits.  That's a
primary reason why rebase was invented, of course.   But teaching
people about rebase vs. merge is highly nontrivial.  "git pull
--rebase" helps a little, but it's still nontrivial, particularly when
local patch #3 of 5 has a conflict.

Also, inevitably, someone will ask "what happened to those simple svn
revision numbers?" or "when I do a merge, why are the patches from
branch #1 interspersed with the ones from branch #2 in git log?"  The
answers are "look at gitk to see the real merge history, that's way
more powerful than svn, and check out git-bisect!" and "use git log
--topo-order" respectively, but those are pretty nontrivial answers
too.

Submodules, which are critical to large-scale software development,
are also very complicated.  You can't explain how to use them without
knowing about .git/config, the difference between that and
.gitmodules, the concept of gitlinks (and therefore the concepts of
trees and blobs), the idea of a "disconnected HEAD" (which all
submodules check out by default), the idea that pushing submodules in
the wrong order ...
From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 11:12 am

Hi,


That _is_ the most common form.

And with my way of not even bothering to tell users that "git pull" has a 
default remote and branch, it is easy to tell users about pulling from 
somewhere else:

	git pull that.big.machine:~gitte/git my-next

No problem.  After having worked with the first form a few time, this 

Oh.  And you have to teach plumbing for that?

Besides, you do not start with that.  Most users will be happy with one 

Funny that you should say that: I had that case.  "git pull origin master" 
said something about conflicts.  Happily, this user was able to read, and 
edited the files mentioned to have conflicts.

After resolving the conflicts (the "<<< === >>>" was known from CVS), add 

No.  Nobody needed that.  All except one user were content with "git 
diff".  That one wanted "git diff --ours".

So there was no use to teach some advanced concepts there, let alone in 
the first few lectures.

But back to the subject: what does this have to do with plumbing?

I will not even bother to reply to your mentioning rebase, submodules, and 
the "complicated" log due to merges for that very reason: all of this can 

Aha.  So we changed porcelain recently, in a backwards-incompatible way?  
Now, that is news to me.

Ciao,
Dscho

--

From: Avery Pennarun
Date: Wednesday, July 16, 2008 - 11:35 am

In svn, a branch is a revision-controlled directory.  In git, a branch
is a "ref".  What's a ref?  Well, it's a name for a commit.  What's a
commit?  Well, it's a blob.  What's a blob?  Err, that's complicated.
What happens when I delete a branch?  Well, it's still in the reflog.
What's the reflog?  Well, it's the local revision history of each
branch.  Local?  Why not shared?  In svn, the revision history of each
branch is shared, but in git, you don't need to, because...

Even git branches are surprisingly concept heavy, unless your users
ask a lot fewer questions than mine.  The really critical question is
why it's so easy to delete a branch in git, and that leads rapidly
into the commit-tree stuff, which is always a spiral into plumbing as


My point was that the porcelain doesn't even make that stuff easy, and
thus you need to understand fundamental git internal concepts to use
them, and fundamental git internals are easiest to teach using the

There are frequent discussions on this list about changing the output
of various porcelains vs. plumbing.  Improving the porcelain output is
useful, because a lot of it right now is mostly accidental (especially
error and progress messages), and to make git easier to use over time,
it will presumably want to be cleaned up.

But if I write a script that uses git and I need to parse the output,
those very useful porcelain changes are backwards incompatible.

The common advice in that case is to only write scripts that use the
plumbing, not the porcelain.  That's fine advice, I think.  But in
svn, I can write scripts using the "svn" command, because its outputs
never change.  Quite unadvanced svn users write shell scripts around
svn, including basic things such as:

   svn status | grep ^C

...to list all conflicted files.  I don't think a similar script
around "git status" is guaranteed not to break.  Perhaps I've
misunderstood though.

Have fun,

Avery
--

From: Theodore Tso
Date: Wednesday, July 16, 2008 - 1:13 pm

I don't think you need to go into the plumbing to explain the commit
tree.  What I normally do is tell people that branches point at
commits, and that commits are identified by commit ID's, which can be
full SHA-1 hashes, or which can be abbreviated for convenience's sake.
It's not strictly necessary to tell them about the commit-tree
plumbing command; just that each commit creates a snapshot, and that
commits can have one or more parents, plus the commit mesage, plus the
snapshot.

I do absolutely agree with Johannes' assertion that you don't have to
explain commit-tree, git-rev-list, and all the rest.  The only reason
why users will need to see git-rev-list is because git-log references
it so prominently, and some of the more powerful git-log options are
only documented in git-rev-list.

							- Ted
--

From: Daniel Barkalow
Date: Wednesday, July 16, 2008 - 2:53 pm

You're simply wrong. A ref isn't a name for a commit (the point of having 
a ref is that it doesn't persist in naming the same commit). A commit 
isn't a blob. If you start telling people complicated and wrong things, 
they're surely going to be confused.

Git maintains history as a directed graph, with each commit pointing back 
at its history. Refs are the what holds the newest commits that nothing 
else points back to. If directed graphs aren't in your users' experience, 
you can put it this way: git maintains history like knitting, where each 
new stitch holds on to one or more previous stitches, and refs are the 
knitting needles that hold the ends where you're working (except that 
knitting is a lot wider than software development). gitk --all even 
provides the diagram you want to explain it.

SVN branches are incredible confusing because they fail to distinguish the 
directory structure of the project's source tree from the arrangement of 
available latest versions. And the version numbers for your branch 

I don't think the plumbing does a particularly good job of elucidating the 
fundamental git internals; the plumbing does single operations on the 
fundamental structures, but that doesn't explain what the fundamental 
structures are, or what they mean, or why you'd do particular things to 
them. In fact, they don't at all show the difference between what's 
expected to change frequently and what's permanent, which will tend to 
give you wrong ideas.

And for understanding the basic objects, "git show" will work better than 
"git cat-file" (there's no fundamental reason that trees are binary data 
and other types aren't, and no particular reason to care about the time 
format in commit headers, etc), and the plumbing programs for creating the 
fundamental objects are an even more uneven and arbitrary presentation.

	-Daniel
*This .sig left intentionally blank*
--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 11:18 am

Well, you are wrong.  Even when people work only with a single branch
'master', once you have more than one repository involved, there's already
merging.  Dscho just described how he would guide new people into the
process without going into the details in that message, by the time his
audiences need merge conflict resolution they are already comfortable with

I've never seen anybody who finds "diff :{1,3}:path" *useful*.

Well, if you are coming from SVN or CVS where a merge is just a large goo
of everything that happened on a side branch squashed into one, perhaps it
might look useful.

What you should learn and teach instead is:

	git log -p --merge

This shows individual changes from the commits involved in the conflict
with rationale (of course your committers must be disciplined enough to
write usable commit log messages for you to take full benefit of this).
Add path/to/filename if you want to process one path at a time.  Also
adding --left-right to the command line may make it more understandable if
you are merging two histories, both of which are from other people, and

Please don't talk nonsense if you do not know history.  I invented rebase
primarily because I wanted to help e-mail based contributors.  There is
nothing about merge avoidance to it.

You can skip merges with "git log --no-merges", just in case you didn't
know.

I won't comment on the remainder but that is not because I agree with
anything you said there ;-)
--

From: Avery Pennarun
Date: Wednesday, July 16, 2008 - 11:51 am

Dunno.  I use it frequently, and it works great for me.  Perhaps my
brain is just poisoned by svn.

I've never tried "git log -p --merge".  I'll try it next time.  This
is certainly not common knowledge, however.  (But to save Dscho the

Sorry, I mixed up git-rerere and git-rebase.  From git-rerere's man page:

       When your topic branch is long-lived, however, your topic branch would
       end up having many such "Merge from master" commits on it, which would
       unnecessarily clutter the development history. Readers of the Linux
       kernel mailing list may remember that Linus complained about such too
       frequent test merges when a subsystem maintainer asked to pull from a
       branch full of "useless merges".

Nowadays, I'm pretty sure people use git-rebase to avoid this sort of
problem (or "git pull --rebase" presumably wouldn't have appeared),
but I can now see how git-rebase was not written *for* this problem.

Anyway, my point was that git-rebase (or at least git-rerere and
git-reset) are needed if you want to avoid a lot of merge commits.
And, to relate it back to this thread, git-rebase cannot possibly be
understood without understanding git internals, and git internals are
easiest to understand by learning the plumbing.

svn avoids these excess merges by default, albeit because it puts your

Perhaps this is mostly a user education or documentation issue.  I
know about --no-merges, but it's unclear that this is really a safe
thing to use, particularly if some of your merges have conflicts.
Leaving them out leaves out an important part of history.  Do you use
this option yourself?

Have fun,

Avery
--

From: Petr Baudis
Date: Wednesday, July 16, 2008 - 11:59 am

Whereas if you rebase, not only you don't show the conflicts resolution,
you didn't even _store_ it in the first place. That isn't much of an
improvement. :-) (This is the main reason why I prefer to avoid rebase
unless absolutely necessary for the workflow.)

				Petr "Pasky" Baudis
--

From: Avery Pennarun
Date: Wednesday, July 16, 2008 - 12:22 pm

The key here is that I'd expect "git log -p" with a rebased merge at
least shows me the actual changes that are in my repository.  "git log
--no-merges" will actually omit things.

Avery
--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 12:09 pm

By default?  As if it has other mode of operation.

Of course if you do not allow any commits in between to make the history
truly forked, you won't see merge commits.  It is like saying that you
like your broken keyboard whose SHIFT key does not work because you think
capital letters look ugly and your keyboard protects you from typing them
by accident.

Is that an improvement?

I won't waste my time further on the apples and rotten oranges comparison,
but you should perhaps listen to Linus's talk where he talks about why it
sucks that SVN/CVS _encourage_ you to keep your local changes uncommitted

Very rarely.  When I run "git shortlog" for summary, it often is handy,
but otherwise no.
--

From: Avery Pennarun
Date: Wednesday, July 16, 2008 - 12:29 pm

I find it interesting how git usability discussions tend to go.  It
usually starts out by someone saying, "Look, git really isn't that
hard to learn, just do it like this..." and then someone says, "But
actually, that's still really complicated.  Everyone thinks xxx other
VCS is easier to learn.  Here's how they do it..." And then someone
says, "Yeah, but xxx VCS sucks!" and that somehow makes it okay that
git is empirically harder to learn than xxx VCS, as anyone can see by
browsing the web.

svn is fundamentally broken, but just because they did *some* things
wrong doesn't mean they did *everything* wrong.  You can learn lessons
even from your inferiors.

Have fun,

Avery
--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 12:34 pm

I agree in principle, but read what you wrote again and realize that your
criticism does not apply to this case *at all*.

You said svn makes it easier because it makes it very hard to do merges
and forces users to stay away from them.  This results in user doing "svn
update" which is to resolve conflicts with large uncommitted changes but
keeps the history straight single-strand-of-pearls.  

I am not saying the merge based workflow in git does not have any room to
improve.  I am just saying that there is nothing we can learn from svn in
that area.  "Solves it by not letting us to do merges" is not a solution.
--

From: Avery Pennarun
Date: Wednesday, July 16, 2008 - 12:46 pm

What svn does is essentially an unsafe version of

       git stash && git pull x y && git stash apply

And that's actually a good example of what I'm talking about; in svn,
that's just "svn up", which is a daily operation that's easy and
leaves a clean, linear history.  In git, it takes three commands
instead of one (and 'git stash' wasn't anywhere in Dscho's list of
commands he teaches to newbies).

I think there's value in thinking about the relative convenience of
svn's workflow for novice users in their day-to-day lives.  Now, in
the case of svn, that "convenience" also leads to novice users blowing
up the local changes in their working copy occasionally, but that's
just an svn *architectural* problem.  Git doesn't have that
architectural problem.

To be more concrete: would anyone object to a patch that simply made
'git pull' include the above stash commands (or something like them)
by default, rather than giving up when dirty files would be changed?
Or can we do even better?

Have fun,

Avery
--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 1:12 pm

If you are advocating that mode of operation to be easy in git, you should
think again.  That pull (be it with or without --rebase) can conflict and
you would need to resolve it, and then your "stash pop" can conflict
again.  You can have your own "git avery-up" alias which is your "svn up"
equivalent, but if you train users with that first, the users have to
learn how to cope with conflicts in individual steps anyway.

Making these three into a single alias is not an improvement either.  If
you are not ready to incorporate other's changes to your history, why are
you pulling?  Being distributed gives the power of working independently
and at your own pace.  You should train your brain to think about the
workflow first.  "You should stash before pull" is _not_ a good advice.
"Do not pull when you are not ready" is.

Suppose you are about to finish something you have been cooking (say a
series of five logical commits), you've made three of these commits
already, and what you have in your work tree and the index is to be split
into the last two commits.  Somehow you learn that $x above has a updated
version.

Yes, running "git stash && git pull --rebase && git stash pop" would be
better than running "git pull --rebase" alone from that state.  But that
would mean your history would have your first 3 commits (of 5 commit
series), somebody else's totally unrelated commits, and then you will work
on finishing the remaining 2 commits on top of it.  Why?  Why is such a
bogus linear history any better?

With git, instead, you have the choice:

	* "git fetch" first to see if it is truly urgent; otherwise you
          don't even have to pull.  First finish whatever you were doing
          and then make the pull

	    $ make commit 1
            $ make commit 2
            $ git pull

	  This results in a merge but it is a good merge.  The resulting
	  history shows your 5 commits are isolated work independently
	  developed while that urgent thing was being done ...
From: Theodore Tso
Date: Wednesday, July 16, 2008 - 3:32 pm

What I've found is that some people will take that advice, and other
people won't.  Saying that you are thinking about things the wrong way
doesn't really help for people who have been so ingrained into an old
way of doing things.  Indeed, it can end up sounding very elistist.

So from a pedagogical perspective, what I would probably do is show
them how to replicate svn-up, and explain to them how this script
works:

#!/bin/sh
# git-up

if git diff --quiet && git diff --quiet --cached ; then
	git pull $*
else
	git stash ; git pull $*; git stash pop
fi

And then tell them that if this put this into their path, then "git
up" will work the same way as "svn up" --- but that git has a better
way of doing things, and why it is so.  And then what I would tell
them is that no really, merges are really easy with git, and that even
if they were to rely on the "git up" alias as a crutch, that over time
they would find that there are much more natural, easy, and powerful
ways of doing things.

In general, I find that people are more willing to listen to "we have
a more powerful way of doing things", if you can first give them the
equivalent of the "dumb and stupid" way that they are used to doing
things so they can switch to the new tool right away without too much
of a steep learning curve; they will then switch to the more
advanced/powerful workflows at their own pace.  Other people may have
other pedgogical techniques, but I find mine to work fairly well.

Regards,

						- Ted
--

From: Sean Kelley
Date: Wednesday, July 16, 2008 - 3:53 pm

Hi




When one has 100 users in a company using a DVCS, you really need some
sort of simplified workflow documented and taught.  Not everyone who
writes code is particularly keen on the vagaries of a VCS' commands.
I know that must be shocking to this audience the GIT list, but it is
very very true.  They don't give a crap what sort of weird command
combination one can pull out of the 100 or so commands when you type
git-<tab> at a bash prompt.  They just want the damn thing to behave
in a somewhat friendly fashion.  They want to check in their code and
get on with software development and not over analyzing how many ways
they can do the same command.   In my experience, what Ted is
suggesting is the only way to handle it.  Most developers just want it
to work and focus on debugging their project.  Never expect your users
to have the same interest as you in VCS.

Sean
--

From: Nigel Magnay
Date: Wednesday, July 16, 2008 - 4:17 pm

That totally mirrors my experience.

Unless you're teaching people totally new to SCM, they're likely to
have experience of something else, and are likely to ask 'but how do I
do xyz'. And sometimes the reply is rather embarrassing, as the new
and powerful way involves 5x as many commands. That's where it gets
the reputation of complexity (when actually it might be more correct
to be a reputation of verbosity).

I tend to actually avoid the commands (porcelain or plumbing) to begin
with, and actually concentrate on the data structures (commits, blobs,
index etc) - then how various people's repos look when you do
particular commands. That way people tend to relax about the many
commands as they can grok that there's probably lots of things you
need to do bit by bit, but that aren't relevant to understand right
now - this seems to help in abstracting away the complexity without
sweeping it under the carpet.

So I pretty much agree. Your set looks good, but I always do fetch and
merge before pull, and also add rebase at the end.
--

From: Stephen Sinclair
Date: Wednesday, July 16, 2008 - 8:21 pm

Wouldn't this be confusing if they have a few commits on the local
branch that aren't yet pushed to the remote branch?
They could suddenly have conflicts that have nothing to do with the
working tree, which could throw people off.  Not to mention the
meaningless merges that clutter the gitk display.

I know I was personally pretty confused the first few times this
happened and I had little trapezoidal patterns in gitk showing 2
commits being automerged between the local and remote branches.  This
was before I understood the concepts of local and remote branches.

Perhaps some warning when...

if git diff --quiet origin/master HEAD; then...

Personally I've since learned that git-pull is a command to think
about a little before doing, as opposed to svn up, since you might
have to resolve things you aren't prepared for, and we're trying to
avoid teaching git-reset here.  I've had to untrain myself from using
git-pull, switching to git-fetch/merge more and more often, because I
keep doing stupid 3-commit merges by mistake when I didn't intend to.
Some tracking of what's been pushed and what hasn't is helpful to keep
things in the expected order imho.


Steve
--

From: Ping Yin
Date: Friday, July 18, 2008 - 10:02 am

Hmm, the first 3 commits are not pushed out, right? So by "rebase",
the history should be first the somebody else's commits
(origin/master), then the first 3 commits, then the remaining 2
commits?:


-- 
Ping Yin
--

From: Dmitry Potapov
Date: Wednesday, July 16, 2008 - 3:24 pm

Everyone thinks so? Somehow, I don't, and there are people who think

Browsing the web is not an empirical study.  And if you say harder, you
should specify to whom. To those who already know xxx VCS, naturally
anything new or different than what you got used to will be difficult
at the beginning. Naturally, it is easier to learn something if there
are more books and articles about it, or just there are more people who
can answer on any your questions. But with everything else being equal,
do you really believe that SVN or CVS is easier to use than Git if we
speak about learning comparable functionality? What is your argument
for that? "svn update"? Well, it is a sure way to make mess in your
working directoy. So, your argument does not sound very convincing.

Dmitry
--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 3:28 pm

Hi,


I find it not interesting at all, even slightly annoying, that I cannot 
seem to start a perfectly valid discussion about advocating porcelain, and 
trying to even avoid mentioning plumbing in user-visible documentation, 
without somebody highjacking the thread to talk about svn.

I am disinterested in svn.  So disinterested that I do not even want to 
read about it.  What we could learn from svn, we did, positive and 
negative lessons, now there is nothing more to be seen here, please move 
along.

So can those people who have something to say about _my_ subject of 
discussion please speak up?  I think this issue has not been discussed 
properly.

Thanks.
Dscho
--

From: Theodore Tso
Date: Wednesday, July 16, 2008 - 3:49 pm

I've already said I agree with you, but maybe it would be helpful if
you focused the discussion a little more with a concrete suggestion
about how we could improve the user-visible documentation.  For
example, it is already the case that "git help" only shows porcelain
commands, that has been a big step forward.

So a concrete suggestion might be to move the list of plumbing
commands from the top-level git man page to a "git-plumbing" man page.

I'll note that the git user manual is pretty good about avoiding the
use of git plumbing commands.  It's not until Chapter 9, "Low Level
Git Commands" that it start going into the plumbing.  (There are a
couple of mentions of git rev-parse before chapter 9, but that's about
it that I could find).

Was there other git documentation where you think there is too many
references to git plumbing?

						- Ted
--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 5:25 pm

Hi,



I think that would not help much.

As I replied to Dimitry, I could imagine that moving the plumbing into its 

Well, rev-parse is one of my pet peeves this day.  rev-parse is _nothing_ 

Actually, the problem arose with a few "tutorials" on the web, and their 
creators violently arguing for their ways (and me being more and more 
uncertain if they are wrong or me).

And then I saw people on IRC doing the same thing.  Realizing that the 
recipients of the "help" were more confused than before, and just typed 
what was written (they would probably even have typed "rm -rf $HOME") 
because they had given up trying to understand.

Ciao,
Dscho

--

From: Theodore Tso
Date: Wednesday, July 16, 2008 - 7:47 pm

I know you don't like hearing about SVN, but normally the tutorials I
tend to point people to, in addition to the standard official git
tutorial and git's user manual, are these two web pages.  First I tell
people to read first part of:

       http://utsl.gen.nz/talks/git-svn/intro.html

which covers the git "philosophy" very nicely, up to the point where
it starts talking about the "git svn" command, and then I tell them to
go read:

	http://git.or.cz/course/svn.html

There are no git plumbing commands in either of those two web pages,
because most SVN users would run screaming if they were given a
tutorial that talked about git-read-tree or git-commit-tree.  :-)

							- Ted
--

From: Craig L. Ching
Date: Thursday, July 17, 2008 - 7:21 am

I've read this whole thread with great interest as I started learning
and using git a few months ago.  While I agree with you to a degree,
there is a class of "newbies" to git who need more than just the basics
that you outlined.  For instance, I'm in the process of evaluating
VCS's, and DVCS's in particular, to replace CVS at our workplace.
Because of that, I need to get "up to speed" as fast as I can.  I need
to know about branches, how to browse history, merging, conflicts, etc.
It is true, though, that I have a lot of experience doing these things
already by virtue of the fact that I've used VCS's for over a decade and
have been evaluating DVCS's for at least the past 3 years, so I have a
bit of a head start on these things.  To learn about these things,
though, the sheer size of Git's vocabulary is huge compared to other
DVCS's.  That's a *good* thing, but it also makes it a bit harder to
learn it all.  It's just a fact of life.

The first DVCS I learned was monotone.  And I think what helped me the
most in learning it is that it's syntax is very simple (you'd probably
say limited compared to git, but that's neither here nor there, if you
stick to your original list, git is as simple as monotone), it's
repository format, the fact that each developer could keep one
repository and create workspaces off of it was perfect for our
workflows.  What I think really helped with learning monotone is that
they had a bunch of common workflows already documented and we could
simply try them out.  Maybe if Git had a few different workflows
documented that might help.  I know we have a "Git for SVN Users"
workflow, but if you want to move beyond that, it might be good to have
some of the more complex workflows documented.  I think some people have
hinted at that suggestion but that maybe it just hasn't been explicitly

Cheers,
Craig
--

From: Petr Baudis
Date: Thursday, July 17, 2008 - 7:51 am

Yes, very recently, someone on #git asked about existing documented
workflows, and there is very little. It would be interesting project for
someone to build a 'Garden of Git Workflows' (or a Labyrinth) - for each
workflow, detailed self-contained documentation ranging from lone developer
with topic branches over repo.or.cz/github forks workflow, the workflows
of "leaf contributors", lieutenants and main integrators of the mail-oriented
kernel/git workflow, up to the single-central-repository workflows.

There are bits here and there, but the main problem is that they are not
self-contained. It might be nice to have something like a set of military
manuals, appropriate for the roles of the particular developers.

-- 
				Petr "Pasky" Baudis
GNU, n. An animal of South Africa, which in its domesticated state
resembles a horse, a buffalo and a stag. In its wild condition it is
something like a thunderbolt, an earthquake and a cyclone. -- A. Pierce
--

From: J. Bruce Fields
Date: Thursday, July 17, 2008 - 8:57 am

That's been requested for a long time, but nobody's gotten around to it.

It might be nice if it could be made a superset of everyday.txt.

--

From: david
Date: Wednesday, July 16, 2008 - 2:16 pm

this is exactly the point that Johannes was trying to make, by teaching 
people these low-level things they get confused and scared. So he is 
suggesting that everyone make an effort to avoid these (at least 
initially)

--

From: Dmitry Potapov
Date: Wednesday, July 16, 2008 - 2:59 pm

You can do "git pull --rebase" if you like. And there is a configuration
option that allows you to avoid typing --rebase every time. Or did you
mean to being to do that without saving your changes? I think the later
is really a bogus idea, and it should not be encouraged. The worst than
that can be only say "svn update" while you still have not saved changes
in your editor. Then you will have even more fun. So the rule should be:
save your changes first, and only then pull from the upstream.

BTW, one thing is to avoid excessive merges, and the other thing is to
do not have this feature at all. SVN is still not capable to merge,
because merge means to have more than one parent. SVN cannot do that.
What SVN does instead is very limited and buggy cherry-picking:
http://subversion.tigris.org/issues/show_bug.cgi?id=2897

In fact, this is not cherry-picking patches but per-file cherry-picking
and due to limitations of their automatic revision filtering, they have
a nice feature -- to edit svn:mergeinfo manually. Obviously, it is
impossible to visualize this per-file property well. Thus when you are
going to merge something in SVN, you have no slightest idea what you are
really doing.

Have fun,
Dmitry
--

From: Stephen R. van den Berg
Date: Wednesday, July 16, 2008 - 1:23 pm

Try --first-parent, it simplifies the history.
-- 
Sincerely,
           Stephen R. van den Berg.

The eleventh commandment: Thou shalt not re-curse!
--

From: Nicolas Pitre
Date: Wednesday, July 16, 2008 - 1:27 pm

I completely agree with you.

In the context of remote tracking branches, I usually talk about
'git init' + 'git remote' + 'git fetch' + 'git merge' and/or
'git rebase' which is somehow simpler to really understand than
'git clone' + 'git pull'.  At that point the branch concept is usually
clear.


Nicolas
--

From: Jesper Eskilson
Date: Wednesday, July 16, 2008 - 10:50 am

Well, Git is not the easiest tool on the market to learn. For people 
used to centralized systems such as RCS/CVS/Subversion, many concepts 
are truly alien. I've recently experienced a transition at our company 
from MKS/SI (a RCS derivative) to Subversion, and the mental gap was for 
many users HUGE. Had we done the transition from MKS/SI to Git, I'm sure 
  several user's brains would have exploded.

 From my perspective, the concept I found most difficult to grasp at the 
very beginning was how the index worked, and many of the introductory 
texts on Git that I looked through only very brielfy explained the 
purpose of the index: Why is it there? Why is it called "index"? How 
does it fit into a typical workflow? Having a CVS/Subversion background, 
it took a while for me to really assimilate the concept.

-- 
/Jesper

--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 11:14 am

Hi,


What does your answer have to do with my mail, i.e. with plumbing?

Ciao,
Dscho

--

From: Jesper Eskilson
Date: Wednesday, July 16, 2008 - 11:19 am

Nothing, really. I just wanted to comment on your note on Git having a 
reputation being complicated.

-- 
/Jesper

--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 11:27 am

Hi,


Thanks, but you also read my note that my users did not find Git 
complicated.  And I think it is not because I am _such_ a good instructor.

Ciao,
Dscho

--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 1:51 pm

I think that justification is harmful.

More productive way to think about it is to identify cases where we _need_
to go down to combination of the plumbing commands in our daily workflow,
with today's command set.  That would give us a good indication that some
Porcelain may need to be enhanced.

An example. I find myself running "git read-tree -m -u $another_state"
while redoing a series inside a "rebase -i" session to move commit
boundaries.  There may need an insn that says "use that tree" instead of
"edit" and running "read-tree -m -u" by hand.  This does not bother me too
much, but there probably are other examples.

Another example.  I often run "git ls-files -u" while looking at which
paths are conflicting.  ls-files is classified as plumbing, but it does
not bother me as much as having to see the staged long object names in
this output.  Other people, however, might find it yucky, and we might
want "git merge --unmerged" or something that lists the paths (and only
paths, no stage information) that still have conflicts.
--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 4:05 pm

Hi,


I agree that if you know Git internals -- and you and me do -- it comes in 
_right_ handy to know the 100+ commands with many options by heart.

However, my point was about telling users, especially new ones.

For example, I would _never_ suggest the following workflow to a n00b 
because it would be confusing:

	$ tar xvf <xyz>
	<try to compile>
	<fix a compile error>
	<fix other things>
	<oh, I could contribute the fixes!>
	$ git init
	$ git remote add -f origin <url>
	$ git read-tree <that-tag>
	$ git status
	$ git add -p
	$ git commit -s
	<repeat until there are no changes left>
	$ git rebase -i origin/master
	$ git format-patch -n origin/master

Even if this is something I did at least a handfull times myself.

Ciao,
Dscho
--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 4:40 pm

Perhaps you did not read my first paragraph?
--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 5:02 pm

Hi,


Well, I did.

But as was visible from the thread including this message:

http://thread.gmane.org/gmane.comp.version-control.git/59935/focus=62021

I take it that we do not really have to go down to the plumbing that 
often.

Sure, advanced usage is nice, and often involves plumbing, especially for 
scripting.  And there is a time to explain plumbing.  But I think that the 
first lesson is not it.  Not even the second or the third.

And as I said in my first mail, I consider it harmful to _start out_ with 
plumbing.

And other answers in this thread (the ones that do not try to highjack the 
thread to talk about a crappy but popular SCM) make me even more certain 
of that.

Ciao,
Dscho

P.S.: Of course, there may be users who like to spend a lot of time 
grasping the internals of Git first, before issuing their first Git 
command.  Just like there are people who like electrodes on their thighs.
--

From: Junio C Hamano
Date: Wednesday, July 16, 2008 - 11:53 pm

Then perhaps I wasn't being clear, and I think we are saying the same

That is not what I am saying.  What I am saying actually is that these
usage that _need_ to involve plumbing is not "advanced", but merely
showing weakness of the current Porcelain.  Fixing that would allow us
move further away from having to resort to plumbing in our daily
workflow.

Perhaps our Porcelains already passed that point, in which case you do not
have to touch the plumbing commands 99% of time during the day and you do
not have to teach new people plumbing at all.  I am agreeing that it would
be a worthy goal to aim for -- I do not however think we are there yet.
--

From: J. Bruce Fields
Date: Thursday, July 17, 2008 - 8:55 am

Is there a way to commit the contents of a tarball without using
plumbing?  I occasionally want to track an upstream that I know only as
a series of tarballs, so I do something like:

	cd repo/
	git checkout upstream
	rm -rf *
	tar -xzvf ../new-version.tar.gz

Then I spend some time mucking around with git-add and git-rm and
eventually end up having to do some sort of git ls-files | git
update-index pipeline.

--b.
--

From: Karl
Date: Thursday, July 17, 2008 - 9:03 am

contrib/fast-import/import-tars.perl

It currently lacks a bit in flexibility, IIRC, but it does its job
well.

-- 
Karl Hasselström, kha@treskal.com
      www.treskal.com/kalle
--

From: Johannes Schindelin
Date: Thursday, July 17, 2008 - 11:16 am

Hi,


How about "git add -u" and "git add ."?

Ciao,
Dscho

--

From: Junio C Hamano
Date: Thursday, July 17, 2008 - 11:29 am

It would work only if new version never removes files.
--

From: Johannes Schindelin
Date: Thursday, July 17, 2008 - 11:43 am

Hi,


You made me doubt for a second there.  But "git add -u" updates the index 
when a tracked files was deleted.  So after "rm -rf *", "git add -u" would 
empty the index.

AFAICT this has been a part of "git add -u" ever since dfdac5d(git-add -u: 
match the index with working tree.), i.e. ever since the "-u" option was 
added.

Ciao,
Dscho

--

From: Junio C Hamano
Date: Thursday, July 17, 2008 - 12:10 pm

I thought everybody would react to my message like so after sending it ;-)
What I failed to say was that the main uneasiness about the above command
sequence Bruce or anybody would have felt would be that "rm -fr *" step,
which in itself look scary and does not remove .frotz that came from older
version.
--

From: J. Bruce Fields
Date: Friday, July 18, 2008 - 7:35 am

Yeah, good point, that's not very careful.

But actually it's "add -u" that I missed--I forgot it would take into
account removed files as well.  Thanks!

--b.
--

From: Michael J Gruber
Date: Friday, July 18, 2008 - 2:55 am

This brings me to a question I never dared to ask so far. In fact, I'm 
happy with git-add and using the index explicitly rather than 
implicitly. Still, sometimes I find my self wanting an "addremove", such 
as in a situation like above. (E.g., tracking a dir which is synced by 
different means.)

Say I have a modified file a, removed file b (rm'ed, not git-rm'ed) and 
a new file c. Then:

git add . would add the changes to a and c
git add -u would add the changes to a and (the removal of) b
git commit -a would commit the changes to a and b (it does add -u + commit)

So, if I want to add and commit all three kinds of changes using 
porcelaine I have to do:

git add .
git commit -a

or
git add .
git add -u
git commit

AFAICT this means that git will scan for modifications to tracked files 
which still exist twice. While this will be noticeable only with large 
dirs on slow FS it's conceptually not so nice. Is there any (porc.) way 
around? I don't know the internals, though; maybe there's no second scan 
(stat...).

Cheers
Michael

--

From: Jay Soffian
Date: Friday, July 18, 2008 - 1:18 pm

On Fri, Jul 18, 2008 at 5:55 AM, Michael J Gruber

I have the following aliased as "addremove":

  git ls-files -d -m -o -z --exclude-standard \
  | xargs -0 git update-index --add --remove

http://www-cs-students.stanford.edu/~blynn/gitmagic/ch05.html

j.
--

From: Johannes Schindelin
Date: Friday, July 18, 2008 - 4:03 pm

Hi,


But that is everything, _except_ easy for newbies!!!

I still suggest "git add -u && git add .".

Hth,
Dscho

--

From: Junio C Hamano
Date: Saturday, July 19, 2008 - 8:27 pm

I'll send out two patches on this topic.

Junio C Hamano (2):
      builtin-add.c: restructure the code for maintainability
      git-add -a: add all files

--

From: Junio C Hamano
Date: Saturday, July 19, 2008 - 8:28 pm

The implementation of "git add" has four major codepaths that are mutually
exclusive:

 - if "--interactive" or "--patch" mode, spawn "git add--interactive" and
   exit without doing anything else.  Otherwise things are handled
   internally in this C code.

 - if "--update", update the modified files and exit without doing
   anything else;

 - if "--refresh", do refresh and exit without doing anything else;

 - otherwise, find the paths that match pathspecs and stage their
   contents.

and it led to an unholy mess in the code structure; each of the latter
three codepaths has separate call to read_cache() even though they are all
"read the current index, update it and write it back" so logically they
should read the index once _anyway_.

This cleans up the latter three cases by introducing a handful helper
variables:

 - "add_new_files" is set if we need to scan the working tree for paths
   that match the pathspec.  This variable is false for "--update" and
   "--refresh", because they only work on already tracked files.

 - "require_pathspec" is set if the user must give at least one pathspec.
   "--update" does not need it but all the other cases do.

This is in preparation for introducing a new option "-a" that does the
equivalent of "git add -u && git add ." (aka "addremove").

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-add.c |   75 ++++++++++++++++++++++++++++++++------------------------
 1 files changed, 43 insertions(+), 32 deletions(-)

diff --git a/builtin-add.c b/builtin-add.c
index bf13aa3..9b2ee8c 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -140,8 +140,6 @@ static void refresh(int verbose, const char **pathspec)
 	for (specs = 0; pathspec[specs];  specs++)
 		/* nothing */;
 	seen = xcalloc(specs, 1);
-	if (read_cache() < 0)
-		die("index file corrupt");
 	refresh_index(&the_index, verbose ? 0 : REFRESH_QUIET, pathspec, seen);
 	for (i = 0; i < specs; i++) {
 		if (!seen[i])
@@ -216,13 +214,36 @@ static int ...
From: Junio C Hamano
Date: Saturday, July 19, 2008 - 8:29 pm

People sometimes find that "git add -u && git add ." are 13 keystrokes too
many.

The support of this has been very low priority for me personally, because
I almost never do "git add ." in an already populated directory, and if a
directory is not already populated, there is no point saying "git add -u"
at the same time.

However, for two types of people that are very different from me, this
mode of operation may make sense and there is no reason to leave it
unsupported.  That is:

 (1) If you are extremely well disciplined and keep perfect .gitignore, it
     always is safe to say "git add ."; or

 (2) If you are extremely undisciplined and do not even know what files
     you created, and you do not very much care, it does not matter if
     "git add ." included everything.

So here it is, although I suspect I will not use it myself, ever.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin-add.c |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/builtin-add.c b/builtin-add.c
index 9b2ee8c..bc02fd7 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -190,7 +190,7 @@ static const char ignore_error[] =
 "The following paths are ignored by one of your .gitignore files:\n";
 
 static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
-static int ignore_add_errors;
+static int ignore_add_errors, addremove;
 
 static struct option builtin_add_options[] = {
 	OPT__DRY_RUN(&show_only),
@@ -200,6 +200,7 @@ static struct option builtin_add_options[] = {
 	OPT_BOOLEAN('p', "patch", &patch_interactive, "interactive patching"),
 	OPT_BOOLEAN('f', "force", &ignored_too, "allow adding otherwise ignored files"),
 	OPT_BOOLEAN('u', "update", &take_worktree_changes, "update tracked files"),
+	OPT_BOOLEAN('a', "all", &addremove, "add all, noticing removal of tracked files"),
 	OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
 	OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip ...
From: Junio C Hamano
Date: Saturday, July 19, 2008 - 8:32 pm

And here is a small test script that makes sure that:

 - both modified and new files are included, and
 - no ignored files are included.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 t/t2202-add-addremove.sh |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh
new file mode 100755
index 0000000..7bf8eda
--- /dev/null
+++ b/t/t2202-add-addremove.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+test_description='git add -a'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+	echo .gitignore >expect &&
+	(
+		echo actual
+		echo expect
+		echo ignored
+	) >.gitignore &&
+	git add -a &&
+	test_tick &&
+	git commit -m initial &&
+	git ls-files >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'git add -a' '
+	(
+		echo .gitignore
+		echo not-ignored
+		echo "M	.gitignore"
+		echo "A	not-ignored"
+	) >expect &&
+	>ignored &&
+	>not-ignored &&
+	echo modification >>.gitignore &&
+	git add -a &&
+	git update-index --refresh &&
+	git ls-files >actual &&
+	git diff-index --name-status --cached HEAD >>actual &&
+	test_cmp expect actual
+'
+
+test_done
--

From: Tarmigan
Date: Saturday, July 19, 2008 - 9:20 pm

It's too bad that 'commit -a' and 'add -a' will have different
meanings.  Are add and commit considered porcelain enough that their
short options could be changed?  Probably not, but it would be nice to
align 'commit -a' and 'add -a' or maybe 'commit -u' and 'add -u'.  I
can just hear people whining about inconsistent flags between

Your reasoning for not using it (which is probably the case for most
people), combined with the inconsistent short options makes me dislike
the short option a little bit, but I like the long --add option.

Thanks,
Tarmigan
--

From: Tarmigan
Date: Saturday, July 19, 2008 - 9:28 pm

From: Johannes Schindelin
Date: Sunday, July 20, 2008 - 3:56 am

Hi,


Two things:

- add and commit are two _different_ operations, not only in name, but 
  also in nature.  The fact that "commit -a" calls "add" is a _pure_ 
  convenience.  It does not change the fact that "add" and "commit" are 
  completely, utterly different.

- if you are a heavy user of "commit -a", chances are that your history is 
  not really useful, because you committed unrelated changes accidentally 
  in the same commit.

The latter point, BTW, is the reason I _never_ teach the "-a" option 
(actually, I teach no option at all) in my first two Git lessons.

Ciao,
Dscho

--

From: Jay Soffian
Date: Sunday, July 20, 2008 - 5:45 am

On Sun, Jul 20, 2008 at 6:56 AM, Johannes Schindelin

I don't like "commit -a" and never use it and wonder why a
short-option was wasted on it.

I do like the new "add -a" (thank you Junio) but I will rarely use it.
I had the "addremove" alias in my .gitconfig specifically because I
used it so infrequently that it was hard for me to remember when I did
need it. So I think that "add --addremove" would be fine and we don't
need to spend a short-option ("-a") on it.

Lastly, I point out that when I started with git, it became much
clearer when I began reading "git add" as "git stage". I think my
first alias was "staged => diff --cached". But I am someone who likes
to learn how the things I use work early on.

j.
--

From: Sverre Rabbelier
Date: Sunday, July 20, 2008 - 1:34 pm

I love it, and the great thing is that auto-complete works on it too!
"git diff --cached" 17 keystrokes
"git stag" 8 keystrokes
That's a 9 keystrokes improvement!


-- 
Cheers,

Sverre Rabbelier
--

From: Dmitry Potapov
Date: Wednesday, July 16, 2008 - 2:48 pm

Yes, it is a good list, and I think it is very important at the
beginning to limit the number commands to 7-8, otherwise many users
may be confused. And, of course, it is better to stay away from all

Most things that we call as "natural" is those that we got used. Once,
you got used to it, it seems very natural, and the index is not
something that is really difficult to learn, but I don't think that
everyone may understand it fully. Some may use Git for many months and
only then suddenly discover that "git diff" does not show all
uncommitted changes, but only changes between their working directory

I think this reputation is largely due to people who open Git user
manual, read about >100 commands, were horrified and stopped learning.
Git is a powerful and very flexible tool, thus to use it to its fullest
you may really need to learn a lot, but it does not mean that you can
use it and be much more productive than with other VCS knowing only a
small fraction of all options. Thus if you can explain to users in terms
that they understood and connect that with their workflow, users may

There is only one thing that seems to be true about teaching Git (or
anything else) -- there is no single method that works equally well
for anyone. Having said so, I must admit that teaching plumbing will
be probably not a good idea for most users, yet there are some who
prefer bottom-up approach. Some users will prefer to connect Git
functionality to their particular needs and solving some practical
tasks that they do day in, day out, while others may prefer to start
with more abstract things like DAG, structure of data, etc... For
the later users, when you explained these basic things, you do not
have to explain commands at all. They may occasionally ask you
something like: git grep works fine for me when I need to find
something in arbitrary file at some particular revision, but how
about finding something in a particular file at arbitrary revision?
Then you say -- look at git log, it should ...
From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 4:19 pm

Hi,



In this case, I have to add that it is natural because it is the way you 
_have_ to do it.  Even if the other SCMs hide it.

You almost never commit a full revision.  You usually update just a couple 
of files.  Now, even CVS has an extra command to add a file, so it accepts 
the fact that staging and committing are two different operations, even if 
"cvs add" does not stage the changes of a tracked file.

Of course, it is easier for us: we can use all the lessons learnt from 

Heh.  I catually would be delighted if one outcome of this discussion 
would be that the user manual starts with a nice big chapter describing 
just my first set of commands, without options.

Another nice outcome could be if all the plumbing man pages were moved 
into a different section, and all the porcelain's man pages would be 
changed to avoid referring to plumbing.

It could be a good idea, too, to explain advanced topics not by command, 

I disagree.  I think that the first steps are the same for everyone.

Ciao,
Dscho

--

From: Stephan Beyer
Date: Wednesday, July 16, 2008 - 3:09 pm

Hi,

Johannes Schindelin wrote:

Basically I agree, but depending on the user's foreign SCM knowledge
it could be useful to talk about some basic "low-level" concepts of git
(without talking about the plumbing).

I mean:
 - objects (commits, trees, blobs ... in very short)
 - index
and perhaps
 - refs (at least branches)

I was told that before I've seen a first git command and I still think
that was very useful.

Hmm, just recalling, my first git commands were:
 1. init
 2. add
 3. status
 4. commit
 5. diff
 6. log
 7. branch
 8. checkout
in this order, approximately. :)

(And I've used rebase before merge and I haven't used clone/pull/push for
a long time.)

It seems I haven't touched any plumbing before I've started with GSoC :)

I also think that for a user it is totally irrelevant if it is plumbing or
porcelain she is using, as long as it works. I mean, if I tought someone
using git, I'd never use the words "porcelain" or "plumbing".

Regards,
  Stephan

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F
--

From: Johannes Schindelin
Date: Wednesday, July 16, 2008 - 4:22 pm

Hi,


So you would say that remembering the name "rev-parse" is just as easy as 
remembering "show"?

You want to say that --keep-dash-dash and --stat are on the same level, 
since both work?  Somehow I don't think so.

Ciao,
Dscho

--

From: Stephan Beyer
Date: Wednesday, July 16, 2008 - 6:01 pm

Hi,


"show" is an intuitional name, "rev-parse" is not.[1]
But that wasn't my point. The point was, that it is not important to a
user whether the tool is called "plumbing" or "porcelain"; that these
terms have no value for the user, if she just wants to get a job done.

Of course, "usually" porcelain is more helpful and as I've said (or
at least tried to say), I don't think there is any plumbing that's
useful for a git beginner.

Regards,
  Stephan

Footnote:
 1. A further comment about the intuitionality or "remembering":
    git-apply is plumbing and has an intuitional name (hence easy to
    remember), git-am is porcelain and does not have one.

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F
--

From: "Peter Valdemar Mørch (Lists)"
Date: Thursday, July 17, 2008 - 12:30 am

As a total git newbie (5 days) coming from svn, I *am* bewildered. Even 
sticking to porcelain, it is a feature-rich new tool I have in my hands!

I'm missing clarity about what is porcelain and what is plumbing. `git 
help` shows

"The most commonly used git commands are:"  add .. tag.

Is this list exactly the list of porcelain commands? Then say so there. 
Neither `git help diff` nor `git help ls-tree` say whether they are 
porcelain or plumbing commands. `git help diff` mentions git-diff-index, 
which i suspect is plumbing. When I read a man page, it would be nice to 
know whether a command (either the topic of the page or another 
mentioned command) is intended as porcelain or not.

Also, I'm guessing that some switches for some porcelain commands have 
plumbing purposes and vice versa. I hope not, but if so that would be 
nice to have documented in 'git help *'

All of this of course assumes that there is consensus and a clear 
distinction between what is porcelain and what is plumbing which I'm 
don't even know if there is.

Peter
-- 
Peter Valdemar Mørch
http://www.morch.com
--

From: Dmitry Potapov
Date: Thursday, July 17, 2008 - 5:38 am

On Thu, Jul 17, 2008 at 11:30 AM, "Peter Valdemar Mørch (Lists)"

There are a few other commands that are considered as porcelain, but they
are not so often used or used for very specific purposes, such sending
patches by email. So, you do not have to bother about them right now.
In fact, even this list may be too long to be learned at once. It is
better to proceed step-wise, like this:

=== Getting started ===
1. Creating your repo
git init
git clone

2. Commiting your changes
git add
git commit

There are also git mv, git rm for those who need them.

3. Inspect your changes before committing them
git status
git diff

4. Inspecting history
git log

5. Synchronization with the upstream
git pull
git push

=== More commands ===

6. How to revert my changes?
6.1. reverting uncommitted changes
git checkout file
git checkout HEAD file
6.2. committed but not publish changes
git reset HEAD^
git reset --hard HEAD^
6.3. published changes
git revert

7. Who introduced this change?
git log -S as better alternative to git blame

8. Some useful "tricks"
git grep
git add -p
git diff --cached
git commit --amend
git show
git log -p

=== Working with branches ===

9. Creating branches and tags
git tag
git branch
git checkout

10. Merging is easy
git merge
By the way:
git pull = git fetch + git merge FETCH_HEAD
git merge branch = git pull . branch

11. What is rebase?
When can it be useful?
Advantages and disadvantages.

=== More "advanced" commands ===

12. git safety net
git log -g

13. Find the change that introduced a bug
git bisect

14. Short review other commands:
git gc
git archive
git-cherry-pick
git remote
git format-patch
git apply
git am


I agree, it is very confusing for beginners. The rule of the thumb that
helped me when I started was that commands with dash in their names are
plumbing (there are a few exceptions though).

Dmitry
--

From: Theodore Tso
Date: Thursday, July 17, 2008 - 5:55 am

The top-level man page has a listing of what is porcelain and what is
plumbing --- although there is some disagreement.  Johannes was
complaining about people using git rev-parse in tutorials and saying
that there was no way that was porcelain, but in fact it is *not*
listed as plumbing in the git man page.  So I don't think there is
really a strong black-and-white category, but rather a certain set of

My personal long-standing complaint is that there are certain man
pages like "git log" where in order to see all of the options which it
can take, the man page for git-log redirects you to a man page for
plumbing.  Great way to scare the users.  :-)


Have you taken a look at the intro-level materials such as "Everyday
Git in 20 commands or so"[1], the git tutorial[2], the official "Git's
User Manual"[3], or the "Git-SVN crash course"[4]?  Those are probably
the best place to begin --- and to basically treat the git man pages
as reference materials with a huge number of controls that you won't
use or need to use for a long time --- if ever.  It's like the 10,000
features hidden inside Microsoft Office.  The features are all
indispensable to *someone*, but everyone has a different set of the
100 features which they all *have* to have.  (And of course, the 20 or

I don't think so.  It's like what the judge said about pornography ---
I know it when I see it.  :-)

And note that there's nothing *wrong* with using plumbing commands.
It's just that from a pedagogical point of view, they might not
necessarily be the best place to start.

						- Ted

[1] http://www.kernel.org/pub/software/scm/git/docs/everyday.html
[2] http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html
[3] http://www.kernel.org/pub/software/scm/git/docs/user-manual.html
[4] http://git.or.cz/course/svn.html
--

From: Peter Valdemar Mørch
Date: Thursday, July 17, 2008 - 6:35 am

Yup. I started there and am happily coding, committing, branching & 
merging away. Now man pages are closest to my fingers in the terminal. :-)

E.g. something I seem to succeed with sometimes, but not consistently is 
the equivalent of "svn revert -R .". "git help reset"? Yup: "git reset 
--hard HEAD ." When I run into merge conflicts, I'll probably look at 
such a doc again, but other than that I'll probably use man pages most.

Just wanted to offer the newbie's opinion, that it would be helpful for 
me with "Here be plumbing. Newbies look elsewhere" notices when I'm on 
my way down the wrong track.

Peter
-- 
Peter Valdemar Mørch
http://www.morch.com
--

From: Theodore Tso
Date: Thursday, July 17, 2008 - 7:26 am

You find quick alias to be a useful replacement for "svn revert -R
<file>" (aka "hg revert <file>" and "bg revert <file>"):

git config --global alias.revert-file "checkout HEAD --"

Once you run this command, you can now do "git revert-file <file>"
which I personally find very handy.  Sometimes I only want to revert
one file, and not all of the files in the working directory, which is
what "git reset --hard" will do.

(Note that "git revert" does something else useful, but which is not
the same as "hg revert", "bk revert" and "svn revert". Oh well, nobody
ever said DSCM's had to be consistent.)

						- Ted
--

From: Junio C Hamano
Date: Thursday, July 17, 2008 - 9:38 am

Good advice.

One caution is that I wrote the Everyday quite a while ago, certainly way
before 1.5.0, and I suspect the set of best commands and best ways to do
what these sections demonstrate to do may have changed.  I do not think
old ways stopped working (that would be a regression), but there would be
better ways invented after the document was last updated.
--

From: Andreas Ericsson
Date: Friday, July 18, 2008 - 1:19 am

[Empty message]
From: Jeff King
Date: Friday, July 18, 2008 - 11:26 am

You might be interested in the "color.ui" config option.

-Peff
--

From: Michael J Gruber
Date: Friday, July 18, 2008 - 3:14 am

Johannes Schindelin venit, vidit, dixit 16.07.2008 19:21:

In an attempt at making not only Dscho happier I suggest a restructuring 
of the man pages in the following way:

In each man page, put a note which says something like:
"This is part of linkgit:gitplumbing[7]." and the like
It should be in a prominent place, such as the last line of "DESCRIPTION".

gitplumbing[7] etc. pages should contain:
- a definition of the respective term together with appropriate usage 
advice (regular use/scripting..., "Let there be dragons.")
- a list of commands like we have in git[1] right now

With the current situation, people don't look at git[1] in order to find 
out what they're supposed to use. It's too long anyways, and could link 
the above pages instead.

If there's enough interest/agreement I'd come up with a refactoring patch.

Michael


P.S.: For me
porcellaine = artistic, fragile
plumbing = plain, robust
Which one would you choose for daily hard work? ;)

--

From: Jon Loeliger
Date: Friday, July 18, 2008 - 11:26 am

I'd like to throw my beef with the main Git man page
out there for consideration as well...

When I hit the man page, which I do on line quite frequently,
I usually use it as an index to get to the real, current man
page for a particular command.  (I am at git.kernel.org for
other reasons all the time, so it is convenient.)

The current sub-setting and organization is painful because
it doesn't have a comprehensive, linear, alphabetized list
of commands from which to select the real man page.  I never
know which "section" to find a given command.  Is it an
Ancillary "manipulator" command?  Or maybe just a "Manipulation"
command, or maybe an "Interrogation" command?  A "Helper"?

I always have to painfully search the page for it instead.

I'm not saying get rid of the Categorical organization.
I am saying, we need a first-page with a straight, alphabetized
command index somewhere easy and located conveniently.

Thanks for listening,
jdl
--

From: Craig L. Ching
Date: Friday, July 18, 2008 - 11:52 am

I don't want to complain too loudly because I don't think I have any
good solutions, maybe yours is a good one, having an alphabetized list
of commands.  What I wanted to second, though, was that I too use the
browser search for all of the Git pages and that indicates that
*something* isn't optimal.

One easy thing I could suggest, and I'd be willing to try submitting
some patches if people agreed it's a valuable change (at least that's
something I think I could handle contributing for now ;-) ) is that when
you hit the "Documentation" link off the main page, instead of going
straight to the Man page, maybe it should go to a page that clearly has
the options that people are looking for.  E.g. a link to the tutorial, a
link to the man page, a link to the Git User's manual, a link to the
FAQ, a link to the "Git for SVN Users" page, etc.  The way it is now,
once you're used to the html rendered man page, it's not hard, but I do
think it's not the most newbie friendly way to navigate the
documentation atm.  Or maybe just feature those links more prominently
at the top of the man page so they're dead easy to spot.  Just my $0.02.
If someone definitively says what should be done, I'd be willing to give

Cheers,
Craig
--

From: Junio C Hamano
Date: Friday, July 18, 2008 - 12:50 pm

When you are on-line (like your case to read kernel.org webpage), it is
rather easy with ^F (or whatever browser you use lets you search).

But I do agree with you that on printed medium we would want a nice
alphabetized list somewhere.
--

From: Johannes Schindelin
Date: Friday, July 18, 2008 - 6:19 pm

Hi,


Actually, I do not particularly like that direction.

Recently, somebody taught me that it makes sense, from the psychological 
view, to stress positive points, and avoid negative terms.

For example, "do not use this" -- even if followed by "use that instead" 
-- is suboptimal.  People will be more stressed, have a shorter attention 
span, and in general recall much less, if you use negative terms.

So what I really would like is this: leave the plumbing pages as they are, 
but enhance those pages that users (especially new ones) are likely to see 
most often.

By "enhancing" I mean to illustrate the principles and commands more in 
term of a select _few_ commands.  And they should describe the options 
themselves, instead of referring to plumbing man pages.

Maybe I'll find some time this weekend to write up a bit more of my 
tutorials, which I would then post so people see what I mean should be 
taught to n00bs first.

Ciao,
Dscho

--

From: Junio C Hamano
Date: Sunday, July 20, 2008 - 1:14 am

Regarding the original "do we want to ever teach plumbing to new users?"
issue, I suspect that, with sufficient enhancement to Porcelain, we might
be able to reach a point where end users can work without ever touching a
single plumbing command at all.

	Side note, that was why I suggested us to first think about use
	cases in our every day work that we still need to resort to the
	plumbing, so that we can identify what that enhancement would
	consist of.

When we reach that point, we might want to restructure the documentation
into two volumes.  One volume for end-users who exclusively use the stock
git Porcelain, and another that describes plumbing commands for Porcelain
writers.

Perhaps move the plumbing documentation to section 3; just like Perl has
DBI.3pm and friends there, /usr/share/man/man3/git-cat-file.3git will
describe what scripts can do with the command.
--

From: Johannes Schindelin
Date: Sunday, July 20, 2008 - 4:02 am

Hi,


I just went back to the thread I mentioned earlier, 
http://thread.gmane.org/gmane.comp.version-control.git/59935/focus=62021

But of course!  I was wondering where to put it, but understanding 
plumbing as a sort of library for shell scripts makes sense absolutely!

Ciao,
Dscho

--

From: Andreas Ericsson
Date: Sunday, July 20, 2008 - 11:41 pm

Half a year or so ago, there were some mailings to the list along the lines
of "what git commands do you use?", using the bash history and a shell
oneliner to dig out some crude intel. Here's mine:
cat ~/.bash_history | grep ^git | awk '{ print $2 }' | grep -v '^--' | sort | uniq --count | sort -nr
     29 status
     26 diff
     19 show
     17 log
     11 branch
      9 grep
      8 pull
      8 commit
      7 fetch
      7 describe
      6 rev-list
      5 help
      4 push
      4 merge
      3 reset
      3 config
      3 clone
      3 add
      2 rev-parse
      2 format-patch
      1 stash
      1 checkout
      1 apply

To be fair, rev-parse and rev-list are on there due to some oneline scripting.
I needed to move commits from several different branches to a single place,

I like this idea, although newbie users may not know what section 3 is for.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231
--

From: Johannes Schindelin
Date: Monday, July 21, 2008 - 3:04 am

Hi,


Actually, I did not even like that approach back then.  Just because you 
happen to be an old-timer and use rev-parse and rev-list frequently does 
not mean that you _have_ to use it, or even _should_ use it, or that it 
would be good to teach your command lines to a newbie.

Ciao,
Dscho

--

From: Junio C Hamano
Date: Monday, July 21, 2008 - 9:22 am

While that stat might be interesting to look at, it does not have 
much relevance to what I was suggesting.



--

Previous thread: Re: [PATCH 0/5] add pack index v2 reading capability to git v1.4.4.4 by Junio C Hamano on Wednesday, July 16, 2008 - 10:04 am. (1 message)

Next thread: Hacks for AIX by Chris Cowan on Wednesday, July 16, 2008 - 10:57 am. (7 messages)