top | item 20004224

More Productive Git

205 points| tosh | 6 years ago |increment.com | reply

143 comments

order
[+] no_gravity|6 years ago|reply
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|6 years ago|reply
On debian this is the default behavior.
[+] saagarjha|6 years ago|reply
If you're on macOS, update your bash and install bash-completions and git. The path above is likely wrong if you're using a package manager: for MacPorts you want to source /opt/local/etc/profile.d/bash_completion.sh, and for Homebrew it's $(brew --prefix)/share/bash-completion/bash_completion (the install process will tell you what to use).
[+] GauntletWizard|6 years ago|reply
Here's mine:

    [alias]
      git = !cd -- ${GIT_PREFIX:-.} && git
This turns my most common typo (starting to type a git command, thinking about it, typing 'git' again) into what I wanted it to be.
[+] BinaryIdiot|6 years ago|reply
I don't know why I never thought to look for more completions for git. This is a great tip!
[+] wincent|6 years ago|reply
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.

[+] jc_sec|6 years ago|reply
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.
[+] jordigh|6 years ago|reply
The proliferation of articles like this is a very very good indication, that, yes, git is that hard, especially if you have to collaborate with other people.

Everyone has a different idea of what git does, what things are called, and different interpretations of the vast git vocabulary. What is a rebase? What is a branch? What is a reset? People have different mental models for all of these things.

Git would be easier if it weren't for all of the git users you have to work with. If you're a git solipsist, you develop your own mental model that works for you and you never have to care what anyone else does when they are using git.

[+] wyldfire|6 years ago|reply
> 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.

[+] ww520|6 years ago|reply
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|6 years ago|reply
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.
[+] XCSme|6 years ago|reply
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.
[+] CardenB|6 years ago|reply
I think both answers are correct, and the best thing is to understand where each approach will bite you.

I prefer to remove the commit because I am proponent of rebasing over merging. Though the issue is that removing merged can be tricky, because you have the merge commit as well as all the commits associated with the merge. It’s easier for me to manage by avoiding merges entirely, and just restructuring git history via rebases often.

[+] mathieuh|6 years ago|reply
You can just revert the revert commit.
[+] tunesmith|6 years ago|reply
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...

[+] AlexCoventry|6 years ago|reply
> 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.
[+] butterNaN|6 years ago|reply
It isn't entirely useless, there's a chance that someone who still has that article can link it here : )
[+] ayushgp|6 years ago|reply
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.
[+] jrimbault|6 years ago|reply
But that's the goal of git -rebasing, merging- conflicts are pointed out to you so that you have to fix them. Fixing conflicts isn't a passive task, it can actually involve writing/modifying code, and by pointing out conflicts git makes it easier.
[+] olvy0|6 years ago|reply
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.
[+] misthop|6 years ago|reply
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

[+] pedro84|6 years ago|reply
> 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|6 years ago|reply
Doesn't look right if an article starts by introducing git reset and git reset --hard.
[+] nagyf|6 years ago|reply
> 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

[+] KwanEsq|6 years ago|reply
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|6 years ago|reply
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|6 years ago|reply
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.

[+] F-0X|6 years ago|reply
On the other hand, I don't know who these articles are really for. I have _never_ met a developer who struggles with git. Not many claim to understand it deeply, but all can rebase, cherry-pick, use the reflog, etc. and almost never do they run into issues.

It mystifies me. Git isn't hard, nor complicated. "Checkout" has a few too many meanings, and thats the singular gripe I have with it.

[+] nlawalker|6 years ago|reply
> Git is a corded drill in a battery-powered drill world

Git isn't a corded drill in this analogy, it's an electric motor: the potential foundation of many different tools for different problems. There's nothing wrong with it, it's just that it would make more sense to use it as the basis of a more complete, ergonomic tool, rather than just sticking a drill bit into the spinning part.

/usr/bin/git is like curl: a command line tool for precise manipulation of an underlying data model/protocol. It's complex, but it works great - if you want to interact with the underlying data model/protocol on its terms. Many people want something that automates a more complex workflow to help them accomplish a higher-level task. For HTTP, we have browsers; for git, we don't have much yet.

[+] misthop|6 years ago|reply
These articles aren't for the Artisan - they are for, in your metaphor, the apprentice and journeyman.

You should do a lot of learning on using a table saw before you touch one. Using git wrong won't kill you, using a table saw wrong will.

[+] anyonecancode|6 years ago|reply
I'm one of those that likes git, finds it decently easy to use, and is much more productive because of it. But I do think there's merit to complaints about git. There's a wide range of experience, skill sets, and programming styles in our industry, and overall this isn't a problem as people can pick up the tools that work best for them. Look at text editors, for instance -- some people use sublime, others intellij, others vim, others emacs, etc. But for version control, there's really only git now. I'm personally a vim user, but I think it would be strange to insist that everyone must use vim.

The text editor analogy falls short in that version control has to be used by the entire team whereas a text editor only has to work for an individual developer. So, I can see the argument that the standard version control tool should be a little more intuitive. I think one challenge though is that, in my experience, it's not even the command line so much as some basic concepts around vcs that people struggle with, so "more intuitive tool" is a hard challenge I think.

[+] jtms|6 years ago|reply
It’s not obvious to me that a battery powered drill is the best tool for the job. If you are a professional doing non-trivial work sometimes the corded drill, with all its benefits, is exactly what is needed.
[+] jacobsenscott|6 years ago|reply
If people would stick to pull, push, commit, and merge 99% of the problems would go away. But there's always one "clean history" OCD nut job who goes ballistic if they see a merge commit in the history. They seem to know everything about git except how to exclude the merge commits from their git log command.

The regular people lose two days of work trying to rebase their merge commits to appease those folks.

Rebase should never have become part of the day to day git toolbox. If it didn't exist nobody would ever see a linear history, and so would never think to care about it.

Thank the maker for github's "squash merge" and "rebase and merge" buttons, which handle all that crap for you. If you're not using a tool that does that for you I'm sad for you.

[+] alkonaut|6 years ago|reply
Agree (And ironically of course some people agree on this in the discussion on every one of these articles).

Git is the C++ of version control. Of course it’s powerful. Of course it can do everything. And of course it’s a huge frustrating footgun with error messages that rival any c++ template compiler error.

The problem is that we have made it a de facto standard so it’s hard to replace. Even if a much better VCS emerged tomorrow, it doesn’t help if there isn’t support in large issue trackers, CI/CD systems, IDEs and so on.

I have great hopes that pijul will be the better git. But again, it’s the tooling and ecosystem that matters, not the qualities of the vcs itself.

[+] dTal|6 years ago|reply
Interesting choice of analogy. Remember Neal Stephenson's "Hole Hawg" essay [0]? He compares UNIX to this ludicrously, dangerously over-powerful hand drill with no safety features and all the ergonomics of a chunk of steel pipe. And by this he means praise! The implication in that essay was that a powerful, dangerous, unfriendly tool is in some way better than a user-friendly tool that lacks the power to remove limbs.

My takeaway from that essay was that in the real world, you will never see a contractor using a Hole Hawg, or anything like it, and hackers have a uniquely fucked-up attitude to human factors. Hackers will excuse the most tragic of user interfaces, with some kind of macho "rite of passage" bullshit. Yes, "macho":

"Now I view them all with such contempt that I do not even consider them to be real drills--merely scaled-up toys designed to exploit the self-delusional tendencies of soft-handed homeowners who want to believe that they have purchased an actual tool."

See? It's all about self-inflicting pain, because if you can't tolerate the pain of a crappy user interface, you're not a real hacker [1]. I see it in the defense of git's crappy user interface ("the reason you can't remember the 50 semi-orthogonal cryptic commands is because you haven't grokked its perfect model of directed acyclic graph theory"). I also see it in the perpetual defense of Emacs' crappy user interface (infuriating, because it is a powerful piece of software). Hell, I even see it in the defense of the command line interface itself (and associated scorn of GUIs) - many of its design decisions have been baked in since 1969, yet to listen to many apologists its perfection is such that it might as well have been carried down the slopes of Mount Sinai by Moses himself.

This is a major cultural problem with our community. Maybe, if we actually could bring ourselves to admit that our interfaces suck, we might start to make a little progress towards fixing them. Because right now, "tolerance for unreasonable bullshit" is a major filter for who gets to do programming.

"...when I got ready to use the Hole Hawg my heart actually began to pound with atavistic terror. But I never blamed the Hole Hawg; I blamed myself."

Yes. Blame yourself. Blame yourself for using a stupid tool with a bad user interface.

[0] http://www.team.net/mjb/hawg.html [1] https://xkcd.com/378/

[+] pjc50|6 years ago|reply
I think experience has shown that some people really like tools that others find really awkward. Sometimes even over the same features described in completely different ways. It is counterintuitive and different from other VCS and reuses commands to mean very different things (especially checkout and reset); that doesn't matter to people who are used to methodically learning these things from first principles.

Plus there's an intrinsic elitism in it being hard to use.

[+] User23|6 years ago|reply
> 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

Tradesmen use all kinds of tools like that, which is why trade schools and apprenticeships are a thing. I bet there are weekly articles on how to get the most out of your Fluke in the trade press, we just don't read them.

[+] blknmild|6 years ago|reply
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|6 years ago|reply
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|6 years ago|reply
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.

[+] objektif|6 years ago|reply
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|6 years ago|reply
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|6 years ago|reply
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|6 years ago|reply
The command line shows you part of the graph: you choose which part it shows you based on what options you pass it.
[+] gwright|6 years ago|reply
You are seeing a path through the graph. If you want the entire graph:

    git log --all --graph --oneline