
How to teach Git - amanzi
https://rachelcarmena.github.io/2018/12/12/how-to-teach-git.html
======
ahartmetz
And here is something to take the garbage quality of Git manpages with some
humor

[https://git-man-page-generator.lokaltog.net/](https://git-man-page-
generator.lokaltog.net/)

"git-eliminate-head eliminates all downstream heads for a few forward-ported
non-counted downstream indices, and you must log a few histories and run git-
pioneer-object --pose-file instead. [...]"

~~~
sonnyblarney
This is funny, but in reality it's not.

Git is one of the most amazing, powerful tools ever conceived, with one of the
must byzantine and ridiculously designed 'interfaces' ever conceived.

People confuse the raw power of a tech, with how well it can be feasibly used.
Sadly, due to the later issues, git will only ever be a shadow of what it
could have been.

With all due respect to Linus, who'd be the first to admit he's not very good
at UI stuff (I mean command line as well)... it's truly a sad thing.

This is a major 'problem that needs to be solved' I'm interested to see how it
could evolve into something 'better'.

~~~
karmakaze
I don't think the complexity of git's command options is a UI problem. It
results from the basis of its operation. We could change some names, add or
remove some concepts to how some of the operations are performed, but there
are simply a large number of actions to handle many edge cases.

A better solution for prose was to always be merging with live multiple
collaborator updates. Conflicts are visible in real-time. I can't see
something like this would work with code. Hmm interesting... unless we only
allow additions and refactorings to working checkpoints.

~~~
P_I_Staker
Yes, I don't really understand all the people trying to "fix git". Git's fine,
though the complexity makes it challenging, especially for new users. However
the complexity is a direct result of useful features. "Keeping it simple" is
great, except when the complexity is needed. I'm hard pressed to name any
features I could do without.

~~~
sonnyblarney
There are two problems: one of inherent complexity, one of UI.

First - the UI is a mess, and that should have been fixed. It would make a big
difference.

Second - is the inherent complexity. That's a good point, but I feel many
things could be hidden or obfuscated.

Most poignantly, Git does something that most of us do not need: it was
designed to work as a 'completely distributed system', i.e. for open source.

Almost none of us do that. 95% of uses cases related to you and I working
collaboratively, on a project together.

The need to have repos which are essentially totally distinct from one another
is a huge source of complexity and it simply doesn't need to exist in most
cases.

So Git is basically an 'admin level tool' that is commonly used in scenarios
for which it wasn't meant to be used, with a confusing interface.

It's costing a lot of time and money and headaches, I do believe someone may
come along eventually and fix it.

This thread is essentially evidence of this - see how many people have
difficult teaching what should essentially be a simple thing in most cases.

Way too many very smart people still spend too much time clustering around in
git.

~~~
fiblit
Ever used a centralized VCS, such as SVN? That seems to be what you want? A
distributed VCS is extremely useful, for mine and many others' uses, however.

------
Derbasti
I have taught git for university classes for some years. To be honest, git is
a mess. It is conceptually not that hard, but the nomenclature is inconsistent
and dangerously ambiguous (quick, what is the difference between reset,
rebase, revert, and checkout?).

The most effective work flow I have found so far, is _teaching_ only
status/clone/pull/add/commit/push. Show them explicitly what happens normally,
what happens when two changes conflict, and how to resolve merge conflicts.
Using git on the command line only.

Then, have the students use git for a big-ish multi-student project. They will
figure out the workflow themselves. After that project, once they understand
the basics, you can talk about branches, debasing, the log and reflog, pull
requests, and all the rest. Don't introduce graphical front ends before this
point.

This method works well. It takes about one hour of teaching, and five weeks of
active use afterwards. Git is a total pain to learn, and can only be
understood by actively using it. I often get very positive feedback for having
taught git.

I have gone through a few iterations with this topic, and have found that
stripping down the initial instructions to an absolute minimum works best. All
those fancy box diagrams are actively harmful to beginners.

~~~
maceurt
I don't know if this is true. For me personally I have had to use git for a
lot of different projects, but I still don't understand anything besides
commit, push, pull, add, and force-push (lol). In my experience you can get
away with just learning those commands, but I still don't feel comfortable
with git.

~~~
marssaxman
Does anyone really feel comfortable with git? I've been using it for over a
decade, in a handful of different organizations, on projects large and small,
both at work and for personal projects, and it still feels like a convoluted
mess. Its terminology is wildly inconsistent and my mental model of its
behavior remains stubbornly full of fog. I have a library of recipes committed
to memory, but I still don't really _understand_ it, and sorting out what's
gone wrong when things inevitably go wrong remains challenging.

------
cyborgx7
Here is my personal recommendation for getting more comfortable with git. Use
"git status" a lot. Everytime you do something in git, and before you do
something, do a "git status" and see what you change with your commands. And
what you didn't change.

Also "git log".

~~~
Ajedi32
`git log` on its own (with no flags) isn't that useful, as it's missing a lot
of important information. I prefer `git config --global alias.lg "log --color
--graph --oneline --decorate"`. Then you can just type `git lg` and get a much
more useful overview of the state of your current branch.

~~~
oblio
Git in many occasions (including when using git log) feels like the designer
just threw their hands up and said:

"F*ck this shit, make your own UI on top if you want to use this tool!"

I don't think Torvalds has a proper excuse for the pain and suffering he's
inflicted on millions of developers worldwide :(

(To the people going: "Oh, it's Open Source!". Sure, so are Mercurial, Fossil,
etc.)

~~~
rkangel
This makes a lot more sense when you realise that Linus thought he was
building a low level tool that people _would_ build a UI on top of. The
'original' git command line was more a proof of concept and engineering tool
than something aimed at actual use.

~~~
WorldMaker
Right, doing a search through the git mailing list for the use of the word
"porcelain" is fascinating. It's unfortunate some of those "porcelain"
projects never finished.

~~~
mcguire
... because none of the power users used them.

~~~
yjftsjthsd-h
Heh. I think Linux on desktop it is like that, at least a bit; frequently, by
the time someone could write a friendly GUI (or friendly CLI for that matter),
they have little use for it.

~~~
zbentley
That's a disturbingly insightful parable for everything from startups to
linux/FOSS contributions.

------
diegoperini
An honest criticism:

If I had trouble with understanding the reason behind add->commit->push
workflow, I would definitely have no idea what this article talks about when
it says things like "merge, rebase, diamond shape". The flow chart looks
almost exactly the same for "pull" and "pull --rebase". The only difference
between the charts is the wording which has no meaning at all for a newbie.

~~~
jamesb93
It sounds stupid but something that really simplified git to me as an absolute
beginner about a year ago was the fact that it doesn't exist on GitHub.
Knowing that git was just something that sat in the folder on your filesystem
and monitored changes took away the notion that there is some kind of sync
between your remote and local. Working just on my own laptop made me realise
how intuitive all the commands and strategies for solving problems were. Then
came pushing, pulling etc between branches and it all just fell into place.

~~~
benwaffle
I wouldn't say it monitors the directory, because there is no git daemon
running. Git just looks at the changes whenever you run a git command

------
iheartpotatoes
This is nice, but I'd like a 201-level handholding on git. I've been using it
for 5 years and I'm still just a clone/commit/merge/(bang head)/push user yet
I know there is tons more it can do that would probably make me more
effective. (I'd also like to switch my team of SVN. Someday....)

~~~
svat
My recommendations:

* Git From the Bottom Up: [https://jwiegley.github.io/git-from-the-bottom-up/](https://jwiegley.github.io/git-from-the-bottom-up/) (PDF: [http://ftp.newartisans.com/pub/git.from.bottom.up.pdf](http://ftp.newartisans.com/pub/git.from.bottom.up.pdf)) (See also: "Linus Torvalds' greatest invention": [http://perl.plover.com/yak/git/](http://perl.plover.com/yak/git/)) Once your mental model matches the program, you'll be able to understand everything, hack your own solutions if necessary, etc.

* Learn Git Branching: [https://learngitbranching.js.org](https://learngitbranching.js.org) \-- in fact I think this should be the UI for Git; wish someone would make that happen (i.e., so that you can point it to any Git repo and get that sort of visualization for it).

~~~
rachelmcarmena
Thanks! Awesome resources! I'll add it to my post as soon as I finish reading
all the answers. I'm learning a lot from you!

------
Fellshard
Humbly, I'd disagree that's the best, though this is a superb _part_ of the
picture to teach Git well. These are nearly the last steps, I would say.

When new colleagues joined our firm and hadn't yet learned Git, the problems
were always the same: uncertainty. They didn't know which Git operations were
safe, and they didn't understand how to perform seemingly risky maneuvers with
zero risk. They're used to even more dangerous tools that can wipe your work
in a second - and, to be fair, Git can as well. The difference is that once
you understand Git, you never have to worry about losing work.

So the way I would teach Git is to honestly start with the graph. Show it in
action with pictures. Show how to always keep references to commits around to
ensure work sticks around. Show how branching and stashing work, let them be
confident that the tool will keep everything right where you left it.

_Then_, once they're confident in the basics, weave in the remote
repositories.

~~~
epage
> So the way I would teach Git is to honestly start with the graph. Show it in
> action with pictures. Show how to always keep references to commits around
> to ensure work sticks around. Show how branching and stashing work, let them
> be confident that the tool will keep everything right where you left it.

Personally, I think this should be coupled with teaching `git reflog` as the
universal undo (as long as they don't `gc`).

~~~
hinkley
Don't teach anybody git gc. The people who really need to find it will come
upon it all on their own.

------
bagrow
Having taught git several times within a data science course I find two
concepts especially worth extra time: WHY there is a staging area, and what is
the difference between “git” and “github”.

~~~
radarsat1
> WHY there is a staging area

I understand your second point, but I have a hard time understanding the
difficulty with this part. Why is it hard for people to understand the idea of
staging?

You put things in a box one at a time before closing the box. Does it require
more explanation than that? What do people find difficult about it?

~~~
JediWing
So I have a solid mental of git, and I understand the theoretical need for the
staging area.

However, I find the occasions for using the staging area in practice are few
and far between, for the simple reason that I can't test and execute the code
that's in the staging area without also having the code from the working
directory also be there. It feels like after having partially staged some of
my working directory, it would be a blind commit with no guarantee that things
are working.

Very rare is the situation that I can break out a list of files over here that
are for feature A and some over there for feature B, and never the two shall
interact.

I think this is probably what most struggle with regarding the staging area,
without being able to articulate it.

~~~
dahart
You never amend commits or rebase locally before pushing? I rebase before
pushing almost every time.

Git’s workflow wouldn’t even be sane without the staging area. This is what
allows you to fix mistakes and make your work presentable for remotes.

~~~
pjc50
> Git’s workflow wouldn’t even be sane without the staging area. This is what
> allows you to fix mistakes and make your work presentable for remotes.

I did exactly the same diff/tidy/diff workflow when I used p4 and svn, neither
of which make a distinction between "working directory" and "staging area".

~~~
dahart
Right, but p4 & svn have “checkout” which is similar to staging. Staging is
part of what we get because we can edit files without having to checkout /
open for edit.

P4 and svn don’t have a strict commit parentage, which is why you can push
commits in those systems in any order. Git’s strict concept of parentage is
what makes the staging area so important for keeping your workflow similar to
p4 & svn Workflows. Without a staging area, you’d either have to always fix
mistakes with new commits, which is bad, or rewrite already pushed history,
which is worse.

~~~
pjc50
> without having to checkout / open for edit.

The terminology is a bit different - unless configured with mandatory locking
(essential for some workflows) you don't have to open for edit. You just edit
stuff and it goes in the "default changelist", roughly equivalent to automatic
staging.

> Without a staging area, you’d either have to always fix mistakes with new
> commits

Mistakes at what point? In the normal svn workflow you can review with svn
diff, then when you're happy do svn commit; it's just that there's no local
place you're committing to. In both cases there's a critical point, either
"svn commit" or "git push".

~~~
dahart
> unless configured with mandatory locking ... you don’t have to open for
> edit.

I’d guess you’re learning toward talking about svn, which I don’t remember
very well, and I am leaning towward talking about p4, which always does
mandatory locking.

You’re right the terminology is different between these different systems, I’m
just pointing out that the git staging area has what you can think of as some
equivalences in the other systems. Or, you can think of it as tradeoffs.
Either way, the git staging area is something that helps you pretend like
you’re using svn or p4 in the sense that it helps support editing multiple
changes at the same time before pushing them to a server.

> Mistakes at what point?

With git I’m referring to mistakes between commit and push. But there’s a
philosophical difference here that I glossed over. With git it’s easier to
commit early and often than it is with svn or p4. With svn & p4 it’s easier to
lose your work because version control doesn’t know anything about it before
you push. If I make micro-commits, which I want and I like, then I put more
“mistakes” along the way into my local history, and I can use the staging area
to clean everything up before I push. With svn & p4, you make those mistakes
and do the cleanup without ever telling the version control, and you run a
greater risk of losing that work while you do the cleanup.

------
Jach
Git itself is so simple, it's all the stuff around it that can be
overwhelming. Social mores about all the possible workflows are maybe the
biggest (rebasing vs merging, granularity of branches and their longevity,
acceptance of partial commits reflecting a state never realized in isolation
on disk, commit hooks, requirement of every commit to satisfy properties
x,y,z, direct access to common parent repo copy vs requiring some sort of pull
request flow (and dependence on github and all their stuff)) but there's also
work tracking, code review, build automation, test automation, deploy
automation...

------
Animats
From the article: _" If you take care the commit history, consider the use of
git pull --rebase. Instead of fetch + merge, it consists of fetch + rebase.
Your local commits will be replayed and you won’t see the known diamond shape
in commit history."_

No, not how to teach Git.

Open source just can't do good user interfaces. The result is almost always a
zillion features in search of an architecture.

Blender managed to almost dig itself out of that hole, but it took over a
decade. Gimp is still down in the pit.

~~~
sephoric
I was just running into this dichotomy this morning. To test my app Autumn on
High Sierra, I had to install it in a VM, so I tried VirtualBox (open source)
and Parallels Desktop Lite (in-app purchases). Not only did Parallels have a
smoother, cleaner, more modern and easier GUI, VirtualBox just out-right
doesn't work when trying to install High Sierra, and I had to find third-party
instructions online just to bypass this bug. Plus it likes to crash right
after shutting down the VM. I'm not really sure if there's some deeper
philosophical reason behind this dichotomy, but I've seen it hold true for a
lot of apps and their open source alternatives, and many people have said the
same thing holds true about my app Autumn and open source alternatives like
Hammerspoon and Mjolnir. As a rule, we really do seem to get what we pay for.

~~~
y4mi
You're pinning THAT on opensource?

a) VirtualBox is an oracle product. That by itself should be telling.

b) High sierra is _unsupported_ as a Guest OS in VirtualBox. You do know what
that means, right?

c) You seriously complain about the darth of open source virtualization for an
OS, which disallows virtualization on anything but apple hardware? ...really?

If you want good open source virtualization you'll want to use Qemu/KVM. Which
obviously doesn't support any apple OS either, because they're not allowed to
virtualize it. Take that up with Apple, not open source

~~~
sephoric
It was the most recent thing I did (literally this morning) so it was fresh in
my mind. I'm also not an expert in virtualization solutions given how I
haven't needed to use it until now. But this has held true for many, many apps
and their open source alternatives. Paid products generally tend to be higher
quality than open source, for whatever reason.

~~~
saagarjha
> Paid products generally tend to be higher quality than open source, for
> whatever reason.

Putting aside the fact that this isn't true, and that there are quite a few
quality open source apps on macOS, it's pretty clear why paid products have
higher quality: the bar for people to buy them is much higher, so they
generally need to be at least somewhat decent for people to consider paying
for them.

------
navinsylvester
No one is appreciating the effort and a different take here. Let me
congratulate the author on job well done.

There are people who love illustrated explanation and for those these are
perfect. This is just meant as a template which others can use to build the
illustrated material and in no way a comprehensive git tutorial.

~~~
e40
I completely agree. I've seen a lot of these, and this one is simple, to the
point and easy to understand.

------
allenu
I gave a git talk at work recently and what I found works was teach the graph
from the beginning. This includes a lot of diagrams of what the graph looks
like as you commit and branch:

\- show what happens as you add commits to a branch \- show that branches are
just pointers to commits \- show what creating new branches looks like, i.e.
creating a new pointer \- show what merging looks like (a new merge commit is
added, or else fast-forward merge and that the branch pointer just moves) \-
show what happens if you don't rebase (i.e. "ugly" non-linear graph) ... then
teach what rebasing does (i.e. creates new nodes and moves the pointer)

I found that building up from the ground up and illustrating graphs allowed
people to conceptualize things much better. There was still some confusion
once merging was introduced (what happens to those earlier commits? do we need
them?) and mostly because people hadn't thought of the graph before.

Git is one of those tools where you can totally do your job just by knowing
the basic commands but not really know what is happening under the surface,
which I think is a testament to the tool. But, that leads people to
conceptualize their own idea of what is going on... and getting it wrong and
being confused when they want to do something outside of their basic toolset.

~~~
da_chicken
Yeah, it was definitely a set of images [0] that made git click for me, but
even those are not necessarily the best pictures to use.

Git's mental model is basically:

> Ok, what if we took our SVN repository and the first thing we did was check
> in an SVN repository to that. So now you check out the repository, and you
> get a complete local repository that you can do anything you want with!

> So Pull/Push are the terms we use for the check out and commit of your local
> repository to the remote repository, and then Checkout/Commit works from
> your local repository just like you're used to with SVN.

And the real magic is what they did by building a system on top of this model
to let you merge changes all the way up while looking at the code like you'd
expect you'd need to.

The problem is that git's toolchain still feels arcane to use, and it
_requires_ that you have good working knowledge of the underlying models. It's
confusing enough that you can't function unless you have that because you
don't know where you are or where you're going. It's a fantastic tool, but
it's like driving a car with two steering wheels, two gear shifters, and six
pedals. Then you say to yourself, "How do I get to the market, buy some milk,
and come right home?" and your brain starts to melt a little bit.

You shouldn't _need_ to know the nitty gritty of how git works internally just
to get it to work right any more than you should need to know how a disk works
in order use a file system, but over and over we keep seeing that knowing that
is really the only way to use the tool correctly and that it takes quite
awhile for people to get.

[0]: [https://blog.osteele.com/2008/05/my-git-
workflow/](https://blog.osteele.com/2008/05/my-git-workflow/)

------
Wehrdo
When I was first learning git, I found an online visualizer like this [0] that
really helped make make concrete the ideas of git history being a graph, and
what different operations did on that graph.

There was still obviously the issue of memorizing the commands, but at least I
knew what the commands were doing on a deeper level.

[0] [https://learngitbranching.js.org/](https://learngitbranching.js.org/)

~~~
collyw
The other problem I find in git is that there are many GUI interfaces and none
of them are consistent. In Eclipse I had a different interface depending on
what project I opened, despite both the projects being in Python.

------
Sir_Cmpwn
I disagree with this idea. The best way to learn git is to read the git book,
in this order: chapters 1, 10, 2, 3, and the rest at your discretion. This way
teaches you about the internals first, and if you understand the internals the
rest of git is pretty intuitive.

[https://git-scm.com/book/en/v2](https://git-scm.com/book/en/v2)

~~~
Mirioron
Great idea. This kind of culture is why there are a lot of people that don't
and probably never will use git.

~~~
someguy101010
The article is about how to get a more fundamental understanding idea on how
git works, and this book demonstrates fundamental ideas on how git works. I
don't see a problem in this reccomendation. If you want just a cursory
knowledge of how to use git to get by, this probably not the right choice, but
that's not really what this discussion is about is it?

~~~
mcguire
Well, that is what the article is about.

------
jecxjo
I like the diagrams, as many explanations often skip the staging portion of
the whole git process. I use that so much that it baffles me that most people
skip it. Then again, I typically don't like having tons of "WIP" commits so I
stage a lot and if I need to switch to another branch I'll commit a WIP that I
quickly `rebase -i` to get back to a clean status.

As for the teaching part, I have found the best results by having you and the
learner actually "working" on the project at the same time on your own
machines both pushing to a centralized server. It becomes too easy to go over
all the commands and feel like you understand it. Most of the scary parts of
git are used when its multiple developers on the same project. And oddly
enough, having the learner do both Developer A and Developer B's tasks don't
seem to work as well as having the learner just do Developer B while I do
Developer A. Trying to explain to someone when to use merge, when to rebase,
and when to use cherry-picking to get the code I just pushed into their
current working branch can be done so much easier when its hands on AND
knowing exactly who is doing what steps.

------
jstimpfle
I found this very helpful: [http://eagain.net/articles/git-for-computer-
scientists/](http://eagain.net/articles/git-for-computer-scientists/). Git's
data structures are well designed. Once you have internalized them, you will
be better equipped to navigate through the jungle of command-line options.

To understand the data structures interactively, use "git cat-file -p HEAD"
and continue drilling down to an individual file in a subdirectory with "git
cat-file -p _OBJECTHASH_ "

~~~
jejones3141
I've never had to understand the internals of a web browser or text editor in
order to use it; drivers ed courses don't start with a discussion of
thermodynamics. Why should it be necessary for git?

~~~
JoeAltmaier
Because every source management tool has a model, and to use it at all you
need to know the model. Else you're jabbing buttons and turning dials on a
complex machine and the outcome is going to be tragic.

~~~
oblio
I've used SVN reasonably well without knowing its internal model. I kind of
knew a bit about it, I'd never call myself an SVN expert and I still managed
to do my job efficiently.

Git fails majorly in this regard.

~~~
JoeAltmaier
Maybe because git has a different model. Learn that, the objections go away.
As the OP attempts.

~~~
oblio
This logic is kind of circular.

"Git sucks, the UX is atrocious, I don't want to spend half my life learning a
tool that shouldn't even need that much hand holding."

"Learn Git!!!"

~~~
delian66
No the logic is not circular, and the advice to learn git is a good one.

It may seem paradoxical at first to you, but is true (as are many things in
this profession). Another paradoxical advice like that, is to learn vim, or
emacs, but I digress.

Git does not suck - as any other tool it, it just has strenghts and weaknesses
(for example working with very large binary assets is its main weakness).

The UX of most common git CLI operations is clean actually, as they are _fast_
, and you do not need many arcane options (although they are there, and are
documented well, for people who read...).

If you screw up something, you just use the reflog to fix the state of your
repo in most cases. Even if you can not (or do not want to), the
troubleshooting is still easy - you can always do a fresh clone from your
remote repository in a new folder and copy what you want there.

~~~
oblio
You're assuming that I haven't read about Git. I've read a ton about it and
its internal data structures. And regarding your digression, I'm a vim user.

Regarding Git, Git does suck. It does the job Linus designed it to do, but
that job is not most software engineers across the world need it to do.

In smaller or in corporate shops, Subversion was almost adequate and several
bad implementation details, mostly related to branching, led to its demise. So
that world needed Subversion++, not Git.

In the FAANG world, there's basically no company that uses Git as-is. It's
strength/weaknesses aka tradeoffs aren't good enough for them.

Git won because tech is a popularity contest and people in our domain like to
do a lot of virtue signalling ("this tool is hard to use, I use it, so I'm
special/cool").

~~~
delian66
My response was to your sarcastic mini dialog above my reply. Do not try to
read other peoples minds - it is impossible, and if you really want to, you
can simply ask.

>> It does the job Linus designed it to do, but that job is not most software
engineers across the world need it to do.

Speak for yourself, you are not most software engineeers.

>>In smaller or in corporate shops, Subversion was almost adequate ...

I have administered SVN profesionally for several years (2005-2007), and was
paid to unfuck screwups made by other developers using it (which many times
involved restoring from incremental _hourly_ backups done on the SVN server
side). Dealing and helping others with their git problems is _many times_
easier.

The FAANG world (which I had to google just now) I imagine has unique
requirements (many teams that must coordinate, super gigantic legacy source
code base), and the resources to do whatever they want (money, humans to
develop and maintain tools and do research). For them, the integration pain
from managing multiple smaller repos may be significant. Outside this world
however, teams are more independant and the source code size is much much
smaller (even for legacy projects).

>> Git won because tech is a popularity contest

You have a point here, but this factor (and network effects in general) is
just inertia, and does not explain why git won, given that for example SVN or
Perforce had such a head start (in tooling, and in mindshare), and there were
other distributed contenders like mercurial and darcs and BitKeeper developed
at aproximately the same time, and even earlier. It won in my opinion because
it was simply superior tech - faster, good enough and very very easy to get
started.

(edited to clean up formatting)

------
QML
As unorthodox as it is, the way I learned Git was through re-implementing it
as a project for the data structures course I was taking [1]. This isn't the
method I would entirely recommend to most people: instead, like the author,
make a diagram for each of the (most-used/basic) commands and sketch out how
they interact with the data structures. [2] is a good starting point.

[1]
[https://inst.eecs.berkeley.edu/~cs61b/fa17/materials/proj/pr...](https://inst.eecs.berkeley.edu/~cs61b/fa17/materials/proj/proj3/index.html)

[2] [https://git-scm.com/](https://git-scm.com/)

------
hwh
I got mixed results with a completely different approach: starting with what
actually exists within a Git repository (i.e. roughly: focusing on aspects of
the plumbing layer first).

However, this only works with people who can make the mental leap to be able
to deduce knowledge of what should be from knowledge about what is. In the
end, I concluded it's a bit like teaching cooking. There are those folks who
need to be taught about full recipes and those who need to be taught about
resources and corresponding steps.

I have not yet seen a working approach to make both of these fractions happy,
unfortunately.

------
syntaxing
This is a pretty great overview! However, I learned Git and Github from
Udacity's free course [1] and it was amazing to me since I am more of a visual
learner. It got me up and running with Git within a week or two. I recommend
others who have no prior experience with Git to check it out.

[1] [https://www.udacity.com/course/how-to-use-git-and-github--
ud...](https://www.udacity.com/course/how-to-use-git-and-github--ud775#)

------
mtrn
I once taught[1] the building blocks of git (basically bullet time view of a
commit) and people found it a bit too theoretical - even though it contained
all the elements, that helped me to understand and appreciate the simplicity.

There is a point, where you go from memorization (add, push, commit) to
deduction (graph, objects and refs) but when this point is reached, depends on
many individual factors.

[1] [https://git.io/fhWxg](https://git.io/fhWxg)

------
meuk
Personally, I think using git from the commandline is too complicated for the
purpose it serves in most companies.

Using a git GUI works quite well for people inexperienced with git.

~~~
abhishekjha
Its opposite for me. I am very comfortable with the command line. It lets me
do crazy things and if I mess up, quitely crawl back to the peaceful place.

GUI integrations have some advantages but the knowledge is not transferrable.
Different GUIs work differently but the commands stay the same. I think both
can complement each other. I use Pycharm a lot and it is a lot easier to see
diffs or file history there. I think the same can be done with cmd as well but
I don’t think I ever bothered to learn advanced commands.

~~~
quietbritishjim
Committing to version control is one of the ideal uses of a GUI. You can skim
your eye over the files you've changed, and flick between their diffs by just
clicking on their file names, before going ahead with the commit. You can
simultaneously cast your eye over recent commits in the revision history. Of
course these are easily accesible with git status and git log (|less) but it's
not the same as dealing with the information graphically.

I would posit the ed text editor for comparison. Why bother with a graphical
text editor (including terminal editors like Vi and Emacs)? After all, you can
look at the context surrounding lines you wish to edit by entering the
appropriate ed commands.

I think it comes down to developers being so used to working with command line
tools that they don't give GUIs a proper chance - ironically the exact
objection they have with less experienced users not using the command line.

------
darkpuma
I think the best thing you could do for novices is to avoid priming them with
preconceptions of Git being difficult. Psyching people up before instructing
them never seems to do people any good, yet it's very common.

~~~
etjossem
I agree with this. For many people who are learning Git for the first time,
it's also their first experience with contributing code to a repository at
all.

The last thing you want to do is turn them off entirely, or gatekeep the
profession to exclude people who aren't good at reading dense documentation.

The best way to teach git is to get them comfortable with "Add, Commit, and
Push" and _then_ explain what's happening at each stage.

~~~
darkpuma
Despite using CVS and SVN for years, I was never truly comfortable with
either. When I first learned git, it was like a breath of fresh air. Suddenly
the VCS was behaving in predictable ways. Yet I'd put off learning git for two
or three years because everybody was telling me _" git is so much more
confusing than subversion."_ I shouldn't have listened to them, and they
shouldn't have said that!

Maybe if somebody has already _mastered_ subversion then git will confuse them
a lot, but I'm not convinced even that is necessarily true. Regardless, it
seems clear to me that novice users shouldn't be told that git is complicated.

------
vngzs
This is missing pointing everyone at a phenomenal ncurses git log viewer:
[https://github.com/jonas/tig](https://github.com/jonas/tig)

And another great bit: always do `git commit -v` for verbose commit edits.
Read your diffs before you commit them.

~~~
deanCommie
How can anyone have a project home page without..showing me why I should use
the project.

Would it have killed Jonas to include a screenshot in the README?

I'm not going to install something just because someone says it's good. I have
to go multiple links deep to get taken to a Flickr gallery, and even then I'm
not sure what is so good about it:
[https://www.flickr.com/photos/jonasfonseca/sets/721576144707...](https://www.flickr.com/photos/jonasfonseca/sets/72157614470764617)

~~~
vngzs
You make a good point, and I was similarly disappointed in the homepage, so
let me elaborate a bit on why I use it:

1\. I want a Git log viewer right in my terminal, that gives me most of the
benefits of visualizing a Git log like a "real" GUI.

2\. Fast startup. I work in dozens of Git repositories a day, many submodules,
etc. To visualize these effectively, I want to type a few characters in my
terminal and see the Git history in a digestible way.

3\. This essentially `git log --graph --pretty` with the ability to deep-dive
into a single commit view of `git log -p` with nothing more than a stroke of
the return key. To exit, I hit ESC.

4\. Vim-like bindings in a Git viewer. Every visual app that I use daily in my
terminal has "roughly Vim" bindings, from Emacs ([https://github.com/emacs-
evil/evil](https://github.com/emacs-evil/evil)) to Zsh (bindkey -v) to Tig.

5\. This is just as fast to start as `git log --graph --oneline`, but I get a
fully interactive view of a Git Repo history. For example, the Linux source
[1].

Perhaps I should compile my thoughts and send some README updates and
screenshots to help the project.

[1]: [https://i.imgur.com/yd7cSd1.jpg](https://i.imgur.com/yd7cSd1.jpg)

------
sramsay
Years ago, I tried to teach git to my (college) students, and it was a
complete disaster. Like a lot of technical things, it's easy to get them
totally confused with a single off-the-cuff sentence (and to be honest, I
think I underestimated how difficult it would be to explain it and the kinds
of pain points they'd encounter).

Reading this article, it occurs to me how useful the idea of a "staging area"
would be to helping them understand. I don't think of it that way myself when
I'm working with it (I suppose I do, but not in those precise terms). But
looking back, that's what was tripping them up. If you're just talking about
local and remote repositories, you're not really giving them the right idea of
the workflow.

------
unmole
I found teaching Git to someone unfamiliar with any other VCS was far easier
than teaching someone who already knew SVN.

------
cben
I only have a sample of 1 (my wife) but I've found Ungit:
[https://github.com/FredrikNoren/ungit](https://github.com/FredrikNoren/ungit)
unparalleled for explaining the graph model behind git — what's a merge, what
it means to fetch vs pull, what's the difference between committing locally vs
push etc...

The specific points that make it great for such teaching:

1\. pretty graph

2\. hovering over actions such as Commit / Merge / Rebase / Push shows what
_would_ happen to the graph if you do it.

3\. you can manually "Move" local & remote branches anywhere you want! This is
mildly risky as a habit, but much clearer to explain than fast-forward and
push, especially with multiple remotes.

4\. automatic fetch that works pretty well (though explicit fetch UI with
multiple remotes is clunky). For people scared of merging and conflicts, it's
liberating to teach "fetch is always safe" and "local commit is always safe",
and that you can fast-forward or merge/rebase separate step.

------
gerbilly
It would be so much easier to use git if there was simply a "git undo" that
would cleanly undo the last git command (or last n commands would be even
better).

Then you could learn more easily via exploration and experimentation.

And I do mean just one command to undo all the things, I _know_ that you can
undo a lot of things in git but each command is different, and I know that
undoing pushes is hard.

------
billpg
Shameless plug: "GIT isn't perfect, and other blasphemies."

[https://blog.hackensplat.com/2018/12/git-isnt-perfect-and-
ot...](https://blog.hackensplat.com/2018/12/git-isnt-perfect-and-other-
blasphemies.html)

(Addresses some of the points raised in this article.)

------
motivated_gear
I like the painting analogy and have used it frequently.

Let's say you were commissioned to create a landscape painting. It'll be a big
payday if you get it right and its due in 30 days.

Because you know you can make mistakes, you make a photo copy of your work
every day and make a stack of them neatly on your desk. This photo copier is
really high quality as copies are made at the molecular level.

On day 16, you find yourself working on the mountains in the picture. You
sneeze and Oh no! You got paint all over your work. But since you have your
copy pile, you just make another copy of day 15 and keep going.

But lets say you think its a lot and want a friend to work on the painting
too. Just allow her to copy your latest photocopy and you both are off to the
races!

Git seems complex but when you bring it down to a practical, non technical
level, beginners pick it up faster :)

------
mettamage
Some ideas on how to teach it non-verbally in class, regarding the add,
commit, push workflow:

In class I'd stand on my right side, so students see me on the left (people
are more used to left to right motions because of reading).

I'd demarcate the working directory, staging area and local repository non-
verbally as 3 different spaces. My most right space (the student's left) was
the working directory, my most right space (the student's right) was the local
repository.

Everytime I'd make a transition from one space to another through add or
commit, I'd make a hand gesture when I'd say "add" or "commit".

In order to add some humor (humor is rememerability) with push I'd point
upwards to the ceiling as if I were looking to God. I'm not religious, but
people got the reference and they all left out loud.

------
hashkb
Many developers view git (and other "helper" tools like text editors, linters,
grep, SQL, ... everything but their programming language) as second-class
citizens.

The way to teach these tools is to make them primary citizens in your company
culture. Emphasize that, without a strong grasp on a variety of important
tools, devs will be unable to perform at or above the bar. Don't promote
anyone to "senior" engineer who can't easily show the benefits of these tools
while a junior engineer pairs with them.

Otherwise, developers will teach themselves the absolute bare minimum
necessary to get their jobs done and go home. The quality of the training
materials is of minimal importance. I learned git because I wanted to be
better at it.

------
jmmcd
I applaud this effort, but it's still not hitting the right notes, eg:

> how to show the changes of a file in the staging area: git diff --staged

Ok, but this shows the diff against what: the file in the working directory,
the file in the local repo, or the file in the remote repo?

~~~
jononor
Agreed that this is lacking. Staged is what will be included in the next
commit (as made by git commit). So it is a diff against HEAD (current commit).

Also, it does not show a particular file, but all the changes in the staging
area. To show only one file have to do `git diff --staged -- src/myfile.c`

------
darekkay
I agree with the author - many developers learn git (or version control in
general) along the way, even though it's a fundamental skill needed for almost
every project out there. This leads to insecurities, inefficencies and wasted
time when (not if) something breaks. That's why our company training for new
graduate hires consists - among others - of 2 days of git/github training. I
love git (even though I might experience some sort of Stockholm syndrome), and
while it's the most popular VCS, it is not an easy tool to learn and should
not be condensed into "commit - pull - push - now start working on some
tickets".

------
mdpopescu
1\. Install TortoiseGit 2\. Use Visual Studio to commit (it automatically does
"git add" with the new files you added to the project - I always forget to do
this manually) 3\. Use TortoiseGit to do "git push", because Visual Studio has
a problem with ssh keys (or at least had a while ago and I didn't bother to
check since) 4\. When something breaks (and it will), google like crazy until
you find a solution

There. I never needed more in a number of companies.

[Yes, somewhat tongue-in-cheek and of course limited to people who use Windows
and Visual Studio, but I have discovered that's a significant number.]

~~~
mazlix
Yeah that's probably a good bare minimum amount of git knowledge. But I feel
like that's making git which can be a super helpful and powerful tool nothing
more than a means to an end.

Learning the functionality of git can really help you out. For example, I
almost always use the `-p` flag (particularly `git add -p` which gives me a
chance to manually see every change I've made, often I'll find some junk that
I may have left somewhere else. Also being familiar with how to rebase series
of commits onto and off of other branches can be a huge time saver.

~~~
wtetzner
> But I feel like that's making git which can be a super helpful and powerful
> tool nothing more than a means to an end.

It also feels like a clunkier workflow than just using git from the command
line. It's probably easier to get started that way, but learning the basics of
git from the command line isn't too hard.

------
daosyn
Just yesterday I attempted to explain to my colleagues (who have been
mainframe developers all their life) the concept of having multiple remote
repositories and different possible setups. I think I explained adding remote
repositories well enough, and mentioned the use cases for such a setup --
having only read access from a repository and needing to develop in a fork
while keeping up to date with the original.

Does anyone have a good analogy for this? I think they understood for the most
part, but explaining things better is something I have been really trying to
improve on in the workplace lately.

~~~
someguy101010
I really think showing them how it works visually with a DAG is a great way to
show someone how git works. Also, Linus has a great talk about git and how it
works here:
[https://m.youtube.com/watch?v=4XpnKHJAok8](https://m.youtube.com/watch?v=4XpnKHJAok8)

(Sorry for mobile link, I'm on my phone RN)

------
hashhar
I feel that Atlassian's git tutorial is the best I have come across so far.

[https://www.atlassian.com/git/tutorials](https://www.atlassian.com/git/tutorials)

------
rhwelc
I've had to teach git to several people. Here is what i teach:

\- never force push (with exceptions) \- don't use reset (with exceptions) \-
don't commit to master \- stop immediately if git tells you, you have 200
changes

Aside from that, people don't really seem to have trouble. Git is pretty
functional with just add, commit, push, pull. People learn more commands as
they need them.

This post was humor

~~~
Accacin
Hahah, once at work a guy force pushed to a branch that was just about to be
merged. This almost resulted in some guys work being lost but luckily it was
recovered.

This was immediately followed by another dev writing 'DO NOT FORCE PUSH' on a
post-it and sticking it to his monitor :D

Edit: I meant merged not committed.

------
mandeepj
I really like these two resources for learning git

[http://ndpsoftware.com/git-
cheatsheet.html#loc=workspace;](http://ndpsoftware.com/git-
cheatsheet.html#loc=workspace;)

Guided tour - [http://gitimmersion.com/](http://gitimmersion.com/)

------
ionmonkey
For anyone looking for resources on teaching git I'd recommend the software
carpentries - all open source with a great community behind it.
[http://swcarpentry.github.io/git-novice/](http://swcarpentry.github.io/git-
novice/)

------
zwischenzug
'How to teach Git' was something I had to think a lot about when a lot of my
technical colleagues didn't know what a rebase was, and asked me to sort out
their 12-team merge history (the 'git log --graph --oneline' spanned the width
of multiple pages before you could see any commit message at all).

I realised that there's a point you can't progress beyond with git without
having to do some thinking and learning. And lots of people aren't interested
in the theory behind distributed file content. So I took Zed Shaw's hard way
method and applied it to git. It made for a really enjoyable course at work
and I then turned it into a book (1).

The tl;dr is I believe you need real world experience with a mentor prodding
you at the appropriate time to think a bit deeper. Then the understanding will
follow.

Here's an example from an 'advanced' chapter:
[https://zwischenzugs.com/2019/01/09/git-hooks-the-hard-
way/](https://zwischenzugs.com/2019/01/09/git-hooks-the-hard-way/)

[1]
[https://leanpub.com/learngitthehardway](https://leanpub.com/learngitthehardway)

------
jbergens
I think it is easiest to show a graphical UI like SourceTree or GitKraken when
you explain git. GitKraken is my favourite but it costs a little money to use
at work.

------
avar
I contribute to git, if anyone's got any UI warts they're bothered by in
particular I'd love to hear about them. Maybe it's something we can fix.

~~~
pletnes
LFS works by installing hooks. This prevents me from adding my own. Also the
one-hook-only policy makes it harder to share hooks.

~~~
avar
Yeah this would be great. I started working on adding support for <hook>.d/*
in addition to <hook> a couple of years ago, that got to a proof-of-concept
stage, but some of the long tail is hard to handle so I dropped it, but it
could be finished.

There was also a disagreement about what the semantics should be, e.g pre-
receive.d/* hooks failing on the first one that failed in glob() order or not,
which has implications for whether they can run in parallel.

The bit that stuck from those patches was being able to configure the the
core.hooksPath variable to a hook path, which _sometimes_ can with some
stretching fulfill some of the use-cases, but most users end up with a meta-
hook runner of some sort.

~~~
pletnes
Glob() is (iirc) not sorted in any way on macos. I would prefer alphanumerical
sort by name as it is stable across OSs.

Parallelization is optimization so I think «make it right, then make it fast»
is sound advice.

~~~
avar
The glob() function is sorted consistently on all platforms. It's mandated by
POSIX[1], and from the OSX docs I could find[2] sorted unless you specify the
POSIX GLOB_NOSORT flag, as on other platforms.

In any case, even if glob() wasn't portable it's easy to provide an API
compatibility layer that's just readdir() + qsort(). That part would be
trivial, and might perhaps be needed due to collation issues in the sort.

Doing it in parallel (preferably in a random order) isn't just an
optimization, but would ensure that there isn't an implicit dependency on
whatever iterative interface we'd first ship with.

1\.
[http://pubs.opengroup.org/onlinepubs/009695299/functions/glo...](http://pubs.opengroup.org/onlinepubs/009695299/functions/glob.html)

2\.
[https://developer.apple.com/library/archive/documentation/Sy...](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/glob.3.html)

------
black-tea
The best way to learn git is to learn what's happening at the DAG level. That
way you can think about what should happen on the DAG and then think of how
you can use git to achieve that. For example, a fast-forward merge and a reset
can be used to achieve the same thing.

It's also very important to learn to use the reflog. When I was learning to
climb they told me I'd never get really good until I'd fallen once. The same
thing goes for git. People are really scared of it because they think they
could lose work or something. Thanks to the reflog and the way git works,
that's actually quite difficult to do.

~~~
e3b0c
I learned that Git stores data as DAG at the very beginning when introduced to
it. But I came to get clicked until I realized that it is not only a DAG but
an _immutable_ one. That is, existing nodes of the DAG are never changed once
created. The only operation supported by the system is more or less: _create_.
Also, using the plumbings to peek into the content of the objects and refs
inside the .git helps a lot as well.

~~~
black-tea
Yeah, that's a very important point. Even changing the parent of a commit,
that is, an edge in the graph, changes the hash of the commit. Therefore to
change the parent (like in a rebase) you have to make a new commit, but the
old commit doesn't go anywhere, you just can't see it because you have no
reference to it any more.

Git will garbage collect these commits that can't be reached by any reference
after a while, but usually that's long after you've forgotten they ever
existed.

------
Walkman
This is very good explanation, but only explains what happens with the files,
nothing about the graph what is a git repository. This talk helped me
tremendously to finally understand what's going on in git:
[https://www.youtube.com/watch?v=1ffBJ4sVUb4](https://www.youtube.com/watch?v=1ffBJ4sVUb4)

It is one of the best talks about git for beginners with an unfortunate title
:D

Also, this interactive visual tool helped me to understand branching:
[https://learngitbranching.js.org/](https://learngitbranching.js.org/)

