
More Productive Git - tosh
https://increment.com/open-source/more-productive-git/
======
no_gravity
Put this in your bashrc:

    
    
        source /usr/share/bash-completion/completions/git
    

And you can type "git br<tab>" to write "git branch", "git checkout fun<tab>"
to write "git checkout funky-feature", "git log --na<tab>" to write "git log
--name-only" etc.

Pretty much every time you press <tab> somewhere while writing a git command,
it does the right type of completion. And hitting <tab> multiple times lets
you toggle through the options. So you learn git along the way.

This was one of my most enjoyable productivity jumps when it comes to using
git.

~~~
dearrifling
On debian this is the default behavior.

~~~
panpanna
Same in Ubuntu.

Bash completion on Ubuntu/debian is out of this world. I can do things like

lxc exec <TAB>

and get a list of currently running containers.

~~~
johnhenry
Fun fact: Ubuntu is a derivative of Debian!

~~~
panpanna
Yeah, but they also have added some stuff that is not part of standard Debian.

------
wincent
The very first factual claim in the article is wrong:

"The most basic usage is: git reset useful_func.clj This will replace the
useful_func.clj in the current working directory with the last committed
version in the repository HEAD."

Not a good start. What it actually does is reset the path "useful_func.clj" in
the index (AKA staging area) to the HEAD state. It doesn't touch the working
directory.

~~~
ecma
It's not clear to me if the author actually understands how staging works and
how that affects the commands they suggest. They claim that stashing takes
staged changes and then note that after stashing the working tree will be
clean. That suggests the post is being dumbed down or the author is
misunderstanding things.

Git guidance should almost always start with a brief introduction to the
concepts you believe the audience doesn't know or fully understand. To begin
with reset and not properly explain the index will just end up being
confusing, especially with brief references to hard, soft and mixed resets
later on!

~~~
narnianal
I see this so often with power user tools. All power user tools are tools that
you can only use reasonably well with some basic understanding. They are made
not to be understood in the easiest fashion but to handle all complexities of
a problemset as efficiently as possible. Therefore it sometimes seems harder
to use from the outside, but actually the hardness comes from the problem it
solves, not the tool.

So yeah, if you really want to use git well, learn its internals. It takes
some time but actually not even hard. After reading the Git Book once I was
even able to implement my own git (of course without performance
considerations).

------
jc_sec
There's an article like this every week or so.. I don't get it. Git isn't
__that __hard.. You can pretty much get by 99% of use cases with like four or
five commands.

~~~
wyldfire
> Git isn't that hard.

It's not, but if you don't use it mostly every day, or if you decide to
"Delete repository and clone again" every time there's a problem, you won't
ever get to learn how to fix it.

The staging area is totally unnecessary IMO. I think git would be easier if we
didn't have it.

The term `checkout` is multiplexed to do more things than I would've guessed.

~~~
ChrisSD
I find the staging area useful. It especially helps when you only want to
commit a change in part of a file or just generally reviewing a commit before
it's a real commit. And also to double check I'm not going to be uploading any
secret keys (which seems to happen to people more often than it should).

~~~
jordigh
The staging area is incidental. It's yet another place in which your code can
be, and it confuses users. This is why Gitless has removed it.

[https://gitless.com/#vs](https://gitless.com/#vs)

You don't need the staging area to select hunks into a commit. The selected
hunks could go straight into a commit. Selecting hunks is a different thing
than putting the selection into an extra intermediate area between working
directory and commit.

You don't need an extra intermediate area to review a commit. Commits are
flexible and modifiable, so you can review the draft commit, modify it as
necessary, and then publish it.

~~~
tom_
I always assumed it was there as an analogue of the state tracked by a UI such
as TortoiseSVN's Commit dialog, or (though it's a lot longer since I lasted
used it...) Perforce's changelists view. It's a list of files you've got
checked out or modified: you tick the ones you want in the commit, right click
to delete files or revert, double click to get a diff, that kind of thing.
Between each deletion/reversion/diff/etc., the state of the tickboxes is
retained, so you can sort of just fool about until you've got what you want.

But this sort of multi-step thing is often a pain to do from the command line,
I find: unless you have some way of tracking the state between commands, it's
no fun working through this list of items, building up a to do list that you
then have to get done at the end with one uber command. And the staging area
is this way of tracking the state when it comes to putting together your
commit.

The gitless examples look to have many common possibilities licked, though,
and perhaps that will suffice for most cases?

------
ww520
Since started using Magit in Emacs, I found myself using the command line Git
less and less. I can perform most Git commands with couple key strokes. Having
a UI with integrated workflow with Git is pretty nice.

~~~
rbavocadotree
Despite using git for nearly a decade, I never became "good" at it until I
started using Magit. Emacs is worth learning for Magit and org-mode alone.

~~~
__MatrixMan__
Vim zealot here. Been tempted by org mode. This comment pushed me over the
edge--I'm gonna give Emacs a try. _Winces and waits for the world to explode_

~~~
zaiste
Long time Vim user here as well. I started my transition to Emacs few years
ago. Along the way I discovered Emacs Doom distribution, which is specifically
created for Vim users (and similar to Spacemacs, but lighter), and I never
looked back.

------
XCSme
One mistake that I saw several times is cherry picking or merging another
branch into the current one, then realizing later that you didn't need those
changes yet, and you _revert_ the merge commit. Later, if you actually want to
merge the other branch into the current one you will get in trouble as it's
already "up to date", as the current branch is ahead. Even worse, if you
instead merge the current branch into the other one, all your changes done in
the other branch will be reverted. The takeaway: don't revert something if you
don't actually want to revert that code. I am pretty bad with git, by I assume
the correct way to reverse the initial merging would be to remove that merge
commit entirely, using git reset.

~~~
mathieuh
You can just revert the revert commit.

~~~
XCSme
Biggest issue is the first part, when it's "already up to date", so then when
you merge the feature into the current branch and think it's merged, it will
actually be missing, so you might forget to revert the revert, or not work
anymore because of new commits/conflicts.

~~~
mathieuh
I honestly can't say I have ever had this problem. I also don't understand how
you could forget to revert the revert? And why would new commits matter? Sure
you may have conflicts, but you would have had them anyway if you hadn't
reverted.

We've had to revert commits on our master branch after several commits have
been added on top before, and we've never had an issue just checking out a
branch off master and reverting the revert commit.

I feel like there are workflow things you could be doing to avoid whatever
problems you're encountering possibly?

~~~
XCSme
You can easily forget if someone else (not yourself) did this (they merge the
branch and reverted it), later when you try to merge the branch it could be
successful, without any merge conflicts, but still won't lead to the expected
changes.

~~~
mathieuh
OK I suppose that is more likely, but I still think this is easily-avoidable
through process. If you're closely-enough involved with a ticket that you were
going to be the one merging it, I think it's reasonable to expect that you
have an idea of things that have happened in the story.

------
tunesmith
I found one article, only one, that did more than anything to help me
understand git. Can't find it anymore. :-( But it had to do with reflog and
how _any_ command could be undone since nothing was truly destructive, and how
reflog actually had the edges in the graph and you just needed to know how to
repoint them to the right nodes. Or something. This is probably one of my
least helpful HN comments.

edit: It _might_ have been this one: [https://hackernoon.com/https-medium-com-
zspajich-understandi...](https://hackernoon.com/https-medium-com-zspajich-
understanding-git-data-model-95eb16cc99f5)

~~~
AlexCoventry
> _any command could be undone since nothing was truly destructive_

As the article mentions,

    
    
        git reset --hard
    

will blow away uncommitted changes in your working tree.

------
ayushgp
One of the most common issue I faced when I started learning git was diverging
local and remote branches, franatically searching how to fix it and giving up
2 hours later.

~~~
olvy0
Yes, that has been my experience as well. Starting a new repo that has a
remote tracking branch has been a source of constant frustration for me. I
routinely mess up some incantation and then have no idea how to fix it. The
mental overload is high enough with local branches, but I still don't quite
follow what it means to have a tracking branch, it seems to complicate the
nice and simple mental picture I have of the local repo as a DAG.

~~~
js2
When you fetch from a remote repo, the state of the branches in that repo has
to be recorded somewhere locally in your repo. That’s what remote tracking
branches are. So if the remote called origin has a branch called master, and
you fetch, git downloads the commits you don’t have and then updates
.git/refs/remotes/origin/master to the commit ID of whatever master is on
origin.

That’s all it is.

Basically you have a DAG just like you think. But git needs some way to label
some of the nodes in that DAG. It calls those labels “references” or refs, it
records them under .git/refs/, and there’s basically just three kinds: local
branches (refs/heads/<branch_name>), tags (refs/tags/<tag_name>) and remote
tracking branches (refs/remotes/<remote_name>/<branch_name>). There’s also the
reflog which is a change log of the local branch refs, and a special log for
HEAD which keeps track as you switch which branch is currently checked out.

Note: if you start poking around under .git (and you should in a toy repo!),
you might not find exactly these files. For performance reasons, git sometimes
combines the refs into a single file called packed-refs.

------
misthop
For many of us git should be a multiplier - spend time doing your code and
experiments in a safe way, because git, used well, will protect you. As such,
learn the tool! Pro Git[0] is great, and you learn the how, but more
importantly the why of the tool, so that you can make git a multiplier.

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

------
pedro84
> We then tell git bisect to run the command lein test on each commit until
> the command exits with a 0 exit code, indicating that we’ve found the first
> broken commit.

According to git-bisect(1), "the script should exit with code 0 if the current
source code is good, and exit with a code between 1 and 127 (inclusive),
except 125, if the current source code is bad."

------
kyberias
Doesn't look right if an article starts by introducing git reset and git reset
--hard.

~~~
derwiki
What makes you say that? I use that command nearly every day.

~~~
kyberias
There is something wrong with your workflow if you have to use git reset
--hard nearly every day.

~~~
jedberg
Why in the world would you say that? I check out a branch, I write some code,
it doesn't do what I want, I do a git reset and try again.

If you aren't using git reset that means you're either a genius coder who
doesn't make mistakes, or you are a coder who would rather keep going down a
bad path instead of just starting fresh. Some people find it easier to just
start fresh.

~~~
claytonjy
For me, it's never the case that new code I'm writing is SO devoid of value
I'd rather pretend I never wrote it, but that's what a reset does. Rather, I
keep iterating until I've made clear progress, then commit.

------
jph
More productive Git is faster & easier with good git aliases. These help
novices and experts alike.

I maintain a large free list of Git aliases, and community feedback is always
welcome.

[https://github.com/gitalias](https://github.com/gitalias)

~~~
jordigh
Here's another one:

[https://gitless.com/](https://gitless.com/)

------
nagyf
> A common workflow is: > Mess up your Git repository. > Google some error
> messages and read cryptic > > posts. > Try a few fixes. > Tear hair out. >
> Delete repository and clone again.

You don’t have to be a genius to use git, I’ve never experienced anything like
this, even though I’ve worked in 15-20 member teams with lots of conflict and
all that. Read the docs and use it as it is suggested. I don’t think it is
that hard... I feel like this scenario is just not from real life

~~~
cs02rm0
It totally is, but probably not for people working with as many as 15-20
others who can help out!

------
KwanEsq
The most productive I've ever been with git is when I've done `hg --config
extensions.hggit= clone git.example.org/repo.git` and got on with my work.

------
chiefalchemist
There's one of these articles at least once per week that makes it to top of
HN. When are we collective going to come to the realization that Git is a
corded drill in a battery-powered drill world?

Don't get me wrong, version control is necessary. Obviously. But if a plumber,
a word-worker or some other artisan used a tool that required a weekly "It's
okay, you'll catch on eventually" article, we would have never got out of the
Dark Ages.

It's time for an intervention. It's time to take seriously the friction and
frustrations it creates. Yes, it has redeeming qualities. But it's time to
stop looking past those and do something about them (other than another
article such as this one).

~~~
finnthehuman
I, on the other hand, see these threads and wonder how arrogant and fraudulent
our industry is when programmers have to pat eachother on the back and say the
problem is git.

Git is a tool for creating and navigating a directed acyclic graph of
revisions. It’s fine to chuckle and make fun about how esoteric that sounds,
but at the same time I expect people that work on my team to rise to the
challenge of proving that they occasionally attended data structures and
algorithms class.

I understand not taking a day to learn git, I really do. It’s hard to find the
time to learn everything that comes your way at work, and you’re not exposed
to the practical challenges that augment documentation as part of learning if
you try to crush it out all at once. But, if someone can’t learn git, I don’t
know what to do with them. We’re not cranking out websites in an agile,
typewriter-pool style open-office, sweatshop. I need people that can learn
things at least as complicated as git, because they’re gonna have to keep up.

~~~
chiefalchemist
> "Git is a tool for creating and navigating a directed acyclic graph of
> revisions. It’s fine to chuckle and make fun about how esoteric that sounds,
> but at the same time I expect people that work on my team to rise to the
> challenge of proving that they occasionally attended data structures and
> algorithms class."

And those can (read:should) have a visual representation, yes? Why are we
still typing archaic/cryptic commands - read: wasting brain cycles that could
be better spent - for what are ultimately manipulation of something best
represented visually?

It's time to move on. I'm sure someone will fax you when the time comes.
Hopefully, you can keep up :)

~~~
bamboozled
There are visual tools for git though, so what's the problem?

\- Gitk

\- Tower for OS X

\- Github

Besides, some people enjoy using CLI tools the obvious reason that they're
simple to use and can be used programmatically with minimal overhead.

------
blknmild
I got shamed a few times in a new role awhile back in part [imo] because it
was assumed I was 1000% git-fluent. The way I’ve started to view svc ticks is
similar to how I view grammar knotsies. In the end the idea is to communicate,
not to make other people feel like dunces.

------
wyclif
My pro tip for 'more productive Git':

Read the Git documentation thoroughly. Most people don't, and then wonder why
they have no idea what's going on when a project they're put on uses Git for
version control.

------
Stratoscope
If you really want more productive Git, stop playing the Git Adventure Game!

When you poke at your repo on the command line, you never get to see it as a
unified whole. All you can do is try a command, see what it prints out, and
try to make a mental model of what this all means.

A good Git GUI will _show_ you the state of your repo and unify all of the
scattered concepts of the command line like the index, the reflog, and
stashes.

SmartGit is my favorite. I've also heard good things about Tower, although
it's only available on Mac and Windows, not Linux. (SmartGit supports all
three.)

A couple of examples from the article:

> _The process of a cherry-pick is brief. First, we identify the SHA for the
> commit or commits you want to pick, using git log or the like. Next, we
> check out the branch we want to apply the commit(s) to. We then pick the
> commits._
    
    
      git cherry-pick d8119f49cd4fd6b0366c5ca3af205f9c25af89ba
    

In SmartGit, you see the commit you want to pick in the log, right click it,
and select Cherry-Pick.

> _Another common issue is committing and then discovering you missed
> something in that commit. Sure, you could make an edit and add another
> commit, but sometimes you want to maintain all related changes in a single
> commit. In this case, you can use the git commit --amend command to fix it
> up._

> _Let’s say you’ve edited useful_func.clj and then committed it._
    
    
      git add useful_func.clj
      git commit -m "Added even more useful function"
    

> _But you forgot to commit your code and document your new function. Instead
> of editing and committing again, you can amend. Make the required changes to
> the useful_func.clj file, then add it again:_
    
    
      git add useful_func.clj
    

> _But instead of running a normal commit, run an amendment._
    
    
      git commit --amend --no-edit
    

> _This will amend your last commit with your new changes and commit it. The
> --no-edit flag tells Git not to launch the editor and skip amending the
> commit log message. If you want to update the commit log message too, you
> can omit this flag._

In SmartGit, you use the same Commit dialog as a normal commit. It's on the
menu, or Ctrl+K (Command+K on Mac) will take you right there. The Commit
dialog has an "Amend last commit" checkbox which is normally unchecked. Simply
check that box and it will do an amended commit. You can either keep the
previous commit message that is displayed in the dialog, or edit it right
there.

A couple of other topics the article doesn't touch on...

What about the index? In SmartGit, you can either use the index or ignore it
as you see fit. I rarely use it myself. The Commit dialog just does the right
thing when I ignore the index, committing my working tree changes directly.
And if I do want to use the index, it's easy to get to from the same dialogs.

One of my favorite features in SmartGit is how it handles the reflog. Instead
of printing out a list of hashes and poking through them to find the one you
need, simply click the Recyclable Commits box in the log view. Now every
commit in the reflog shows up as part of the normal commit log tree. You can
work with these commits just like any other.

It does the same thing with stashes. Click the Stashes checkbox and they show
up in the commit log too. (I wonder how many Git users realize that a stash is
simply another commit by a different name?)

Maybe you're not sure exactly what was changed between two fairly distant
commits? Click one of them, and then Ctrl+click the other. Now the Files panel
shows you exactly which files were changed between these two commits and the
exact differences.

I could go on for a while, but what I really wonder is why so many developers
are reluctant to even _try_ a Git GUI like SmartGit. It is so much more
powerful and productive than the command line adventure game.

~~~
narnianal
> When you poke at your repo on the command line, you never get to see it as a
> unified whole. All you can do is try a command, see what it prints out, and
> try to make a mental model of what this all means.

Or simply learn to use the git commands right. Then it shows you everything
the UI tool would show.

I recommend everybody adding this to their ~/.gitconfig

    
    
        [alias]
            lol = log --oneline --graph --decorate
            lola = log --oneline --graph --decorate --all
            lols = log --oneline --graph --decorate --all --max-count=10
    

Then you can simply do a `git lol` or `git lola` to get the same result as
your fancy UI is showing you. And it also works via ssh. If you've manually
typed that alias in a few times you will also remember it and have it readily
available when you ssh into a customer server etc.

------
objektif
I am not the best programmer around but i gotta sat Git is a disaster to work
with. I find it incredible complicated for such a simple task.

------
francis-io
I often use this to get to the root of a git repo. Put this in your ~/.bashrc

alias r='cd $(git rev-parse --show-toplevel)'

------
crimsonalucard
Any interface that forces you to manually visualize a complex internal
structure rather than show you the internal structure itself is a design
smell.

Any interface that forces me to manipulate such a complex structure with
obscure textual commands rather than a drag and drop interface is a design
smell.

The git graph structure is not amenable to command line. When I do "git log"
it lies to me. I see a linked list for what is essentially a graph.

~~~
saagarjha
The command line shows you _part_ of the graph: you choose which part it shows
you based on what options you pass it.

~~~
crimsonalucard
Without options it returns something that is implied to be a linked list. Try
it. Anything merged into the current branch is shown as part of a single long
list. It implies sequentialism in places that are parallel.

------
dmh2000
thanks for telling me about 'git amend'. I frequently screw up and fail to add
the files I want or as soon as I commit I remember I needed to change
something else. So my projects all have strings of commits that are a few
seconds apart.

~~~
narnianal
`git amend` and `git rebase -i` are two core features of git. It's okay if
especially interactive rebasing takes some time to get used to. But it should
certainly be part of every users standard tool set.

------
sandov
Why does the article link to the version 1 of the _Pro git_ book instead of
the v2?

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

