top | item 40486197

Git cheat sheet [pdf]

328 points| tambourine_man | 1 year ago |wizardzines.com

143 comments

order
[+] nomilk|1 year ago|reply
A couple of hidden gems:

git diff --staged (shows the diff between the last commit and what you've got staged, great when what you're staging is finicky, lets you double check that you have precisely the files/hunks you intended)

git log <file> (git log, but for just commits where <file> was touched; saves pilfering through all of git log, especially useful when the file only gets modified infrequently)

Random tip: when using git add --patch, try the 'e' option if you need more nuance than the hunks git provides (it contains instructions for how to ex/include individual lines, so you don't have to remember how to do it).

[+] m0zzie|1 year ago|reply
Wow, TIL `git diff --staged` exists and is an alias to `git diff --cached`, which I have used for many years. "staged" certainly feels more intuitive, but will I ever be able to undo this muscle memory?!
[+] omginternets|1 year ago|reply
15 years… 15 years to discover git diff --staged !
[+] NobodyNada|1 year ago|reply
> git diff --staged (shows the diff between the last commit and what you've got staged, great when what you're staging is finicky, lets you double check that you have precisely the files/hunks you intended)

If you set `git config --global commit.verbose true`, then Git will automatically include this diff in the comment section of the commit message editor.

[+] 1000100_1000101|1 year ago|reply
One of faves isn't listed.

  git log -LstartLine,endLine:fileName
It's like an extended git blame, showing how the specified lines evolved over time, and by who. Tracks the change as the line numbers evolve, and even as the file is moved.

Answers the questions of "who did this, when, and why?" / "How long has it been like that?", etc.

[+] redbell|1 year ago|reply
"There are only two hard things in Computer Science: cache invalidation and naming things." - Phil Karlton [0]

Based on the above statement, I find it extremely weird to see such git command named "blame", then I realized I'm not the only one:

What does 'git blame' do? [1].

Blame someone else for your bad code [2].

Git blame should be called git credit [3].

Does Git Blame sound too negative? [4].

______________________________

0. https://skeptics.stackexchange.com/questions/19836/has-phil-...

1. https://stackoverflow.com/questions/31203001/what-does-git-b...

2. https://news.ycombinator.com/item?id=27963868

3. https://dev.to/damcosset/git-blame-should-be-called-git-cred...

4. https://www.reddit.com/r/ProgrammerHumor/comments/r5lzyo/doe...

[+] Wowfunhappy|1 year ago|reply
I think `blame` is on-brand for a tool called `git`.
[+] leipert|1 year ago|reply
I think a better name would be “git praise”
[+] thecrims0nchin|1 year ago|reply
I liked the way I learned git. I started with sourcetree, a third party git gui. Super simple to use and understand. Then I moved to git gui, this step could be skipped. Then I got tired of pulling up my UIs and learned the terminal commands. Highly suggest this for anyone new, but just my (n=1) experience.
[+] SoftTalker|1 year ago|reply
All I know of git is clone, pull, commit, and push. That’s all I’ve ever needed. Git can be that simple. Of course it supports more complex uses, which you can learn if you need them.
[+] Barrin92|1 year ago|reply
>Then I got tired of pulling up my UIs and learned the terminal commands

I'd never revert to terminal commands. Git is basically begging to be interfaced with through a GUI given how much sense it makes to visualize a git repo and its workflows. The moment I started using Magit git started to make sense for me.

[+] therealdrag0|1 year ago|reply
Btw I moved from Sourcetree to Fork. It’s very similar but way more performant and smooth UI (unless ST has improved in last few years)
[+] toinebeg|1 year ago|reply
I had kind of the same path but with GitKraken and Sublime Merge but I kept Sublime Merge around as it ease complex interactions too.

I have only praise for Sublime Merge.

[+] tiffanyh|1 year ago|reply
Is there a historical reason why git is needlessly complex?

Seeing this cheat sheet really brings it to life.

[+] vrinsd|1 year ago|reply
Yes. Because git was created by Linus Torvalds specifically to enable and advance Linux kernel development.

The fact it has become so widly adopted is a "happy accident" (or misery). Github I think has been widely credited with making git so common place ("free git hosting") but I don't think git is the "ideal" revision control system for many projects.

Because it was made for Linus for Linus/Linux, this is why the terminology and sometimes workflow is backwards from every other "normal" version control system. A "Pull Request" (PR) is named that because for Linux development Linus/maintainers would PULL changes into Linux kernel tree. In almost every other version control system it's called a Merge Request which logically makes MUCH more sense because you are merging a change (where ever it came from) into a tree.

Git was (still?) the only open-source distributed version control system that could handle enormous code bases with good speed which means it gained a lot of inertia at big companies as well.

I vastly prefer and use Mercurial for personal projects but if you have tried to use Hg on huge code bases (I've tried on Android AOSP) it really chokes. Mercurial got the "user interface" and command-set right and has some nifty features (being able to launch a web server on the fly to get a tree view of your changes) but being written in Python, performance and scalability aren't ideal.

[+] sam_bristow|1 year ago|reply
Some of the complexity comes from the fact that in earlier versions it was reasonably expensive to add new subcommands. As a result more functionality got added to existing subcommands like git checkout. This made the UX more confusing.

In newer versions of git the cost of adding new subcommands is reduced and they've started adding more specific commands like git switch.

[+] wsc981|1 year ago|reply
I think most of the time you’d be ok just knowing a couple of git commands (log, add, commit, pull, push, ..?). And of course there’s also GUI tools.

I don’t think git is that complex for most workflows to be honest. But there is a lot of power that is available if the need arises.

[+] fragmede|1 year ago|reply
It's not needlessly complex. The workflow it was created to support is inordinately complex, and the target market for that is highly technical, so its complexity was not the issue. Kernel developers needed to communicate to other kernel developers in a decentralized manner, and needed to work on top of each other. How do you work on a project where there are 15,000 people writing code? Git was created for this purpose.

It's as complex as it needs to be to support the workflows it was designed to be. A dumber tool would be easy to create, but then it would not be able to support more complex workflows like linux kernel development. So it's not needlessly complex, though it is more complex than it needs to be for simple use cases.

For those needing a less complicated frontend, there's a large number of them to make it easier to interact with git. For people that aren't full-time software developers, I don't recommend using git directly. However for those that are, it's worth taking the time to understand the underlying concepts so git becomes something you understand because once you do, it's quite elegant for what it does. I'm not going to gatekeep being a software developer on whether or not you know git, but if figuring out for yourself how such a fundamental system works doesn't give you a release of dopamine, this might not be your kind of thing. Which is totally fine. There are tons of things that are and aren't my thing.

I recommend https://learngitbranching.js.org for learning how to navigate around git.

but of course, https://xkcd.com/1597/ applies as well.

[+] eviks|1 year ago|reply
Because good UI design requires a different skill and takes extra effort to achieve, so it's most often just ignored
[+] tasuki|1 year ago|reply
Git is not complex. Its UI is!

Git is very simple. It is built on just four concepts: blobs, trees, commits, refs.

[+] jimbob45|1 year ago|reply
Because Linus had more clout in the SE industry than anyone else and said “SVN bad” and nobody wanted to do enough research to disprove him so here we are.

Merging in Subversion is a complete disaster. The Subversion people kind of acknowledge this and they have a plan and their plan sucks, too. It is incredible how stupid these people are.

So for example, let's go back to one of the things where I think the designers of Subversion were complete morons. Strong opinions. That's me, right? There's a few of them in the room today, I suspect. You're stupid. (Crowd laughs)

Nobody is interest in branching. Branches are completely useless unless you merge them.

https://sandeep.ramgolam.com/blog/linus-torvalds-talks-about...

[+] mariocesar|1 year ago|reply
I didn't know about `git add -p`. Really useful!

  -p, --patch
  Interactively choose hunks of patch between the index and the work tree and add them to the index. This gives the user a chance to review the difference before adding modified contents to the index.
[+] Fellshard|1 year ago|reply
I always custom-select hunks of my current work to assemble into coherent commits, where possible. I find it really helps me to rearrange the work I've done in my head in such a way that if I needed to walk someone through it, I could do so by walking the commit line.
[+] ruraljuror|1 year ago|reply
Love this. I would add:

  git commit —-fixup $COMMIT_ID
combined with

  git rebase -i upstream/master —autosquash
These have become staples of my recent workflow. Julia’s example uses HEAD^^^^^ to rebase the previous 5 commits. I have been doing this as HEAD~5, until recently I realized you can just rebase all commits up to the upstream HEAD.
[+] mwpmaybe|1 year ago|reply
Ahh, thank you:

    git commit —-fixup $COMMIT_ID
I'm adopting this immediately. I always make little "oops <topic>" commits like "oops GET users/me" and then manually move and fixup them on my next interactive rebase. This is much better!
[+] lathiat|1 year ago|reply
I only recently learnt this one, it's great for working with stacked patches in gerrit.
[+] wyldfire|1 year ago|reply
The biggest eye opener for me is understanding that all those commits are "still in there". Tags and branches merely point to a commit and the commit that branch used to apply to isn't gone.

Many (probably fair to say "nearly all"?) commands will be non destructive in that you can easily refer to older incarnations of your branch.

I'd seen "git reflog" but mostly used it to remind me of "that branch I worked on a while ago".

I gained a semi-healthy fear of operations that could land me in the middle of a conflict resolution that I wasn't interested in handling right now (often because the conflict occurred because I was referring to the wrong commit/branch).

I haven't completely cured that fear but at least I feel pretty comfortable recovering any old work among rebases, etc.

[+] Zambyte|1 year ago|reply
Jujutsu has 100% cured me of those exact fears. Here are some ways I deal with them:

- I don't know if there will be conflicts when after some operation. I just do the operation and see what happens. If there are conflicts, I either deal with them, undo the operation that caused the conflict, or make a me commit somewhere else, leaving the conflict to be dealt with later.

- I know there is going to be a conflict. In this case I may duplicate the related branches and either try to reconcile them ahead of time, or try to do the conflicting operating and walk through resolving it. If the conflict resolution gets gnarly, I can either undo portions of the resolution and keep trying, put it off and do something else for some time, or abandon the whole tree.

[+] johnwheeler|1 year ago|reply
I'll say it aloud: People need to drop git and look at JJ

https://martinvonz.github.io/jj/v0.17.1/

I think even Linus thinks git has a shitty UI. JJ has an amazing workflow.

[+] pixelesque|1 year ago|reply
Going to have to disagree on the lack of an index: I can see workflows where that's simpler, but I'm so used to that now with git (for better or worse) I'm imagining that'd be a pretty big workflow change for me...

Other than playing around with it, I haven't really used it in anger though, so...

[+] Panzer04|1 year ago|reply
I always find it interesting how knowledge makes it hard to comprehend the difficulties other people have. I used to barely understand git, but after a couple of years working at a company that relies on a rebase workflow, I'd like to think I largely understand how it works. Its nice to recognise pretty much every operation on this cheatsheet.

Is it common that developers still have issues with git after using it professionally for a couple of years? Admittedly, I still have trouble remembering the commands to do what I want (hello, rebase --onto A B C), though :P.

[+] rezonant|1 year ago|reply
One thing missing that I use all the time, "git cherry". Without arguments it will show you what commits in your local branch are not in your remote tracking branch. Use "git cherry <ref>" to list the commits in the current branch that are not in the given ref.

Most simple use is to know what you are about to push. Second use case is getting a commit list for release notes when using deployment/promotion branches.

Super useful, I thought everyone used it but maybe some don't know!

[+] koito17|1 year ago|reply
Cool cheat sheet, especially because it covers common use cases. But practically everything covered here I was able to learn independently with Magit. It's also much easier to press one or two keys in the magit-status buffer than to open a terminal and manually type git commands, so I pretty much never use the git CLI directly, not even for a clone.
[+] abalone|1 year ago|reply
This is great, especially the little diagrams which help illustrate rebasing vs merging, one of the tricker parts of the git learning curve.

Having said that I think it could more clearly state the author's typical preferred practice for updating a branch and integrating it with main when you're done. There's a few techniques listed for diverged branches, but then fast-forward merge is in its own box and it's not super clear how you might use working-branch rebasing with it to eliminate divergences in the first place (even though it's hinted at under "pull changes").

I wonder if it would be clearer to say something like "combining branches: rebase your branch and do a (FF) merge, optionally with squashing," or however they like to do it.

[+] adamsilkey|1 year ago|reply
Maybe my favorite option is missing here.

`git commit -v`

This will put the diff of the commit into your commit message as comments. Makes it easy to remember what you're doing/committing without having to jump back to the terminal/someplace else to look at the diff.

[+] jmercouris|1 year ago|reply
If you aren't already, you can also try Magit. It really helps one master and interact with Git.
[+] geekster777|1 year ago|reply
Every cheat sheet like this highlights the surprisingly high learning curve of the git cli. It's an interface that really ships it's underlying data model rather than optimizing for common workflows. This isn't necessarily a bad thing, but I often feel like the target audience of git is the power user, leaving me uncertain anytime I need to perform an intermediate level action.

Lately I've been enjoying Graphite as a tool to interface with git. Commands are based around atomic actions I want to perform, despite often triggering multiple git commands under the hood. This has reduced my overall mental overhead, and removed many footguns.

[+] pncnmnp|1 year ago|reply
I have a funny little habit that probably stems from a certain degree of paranoia when working on a decent-sized change. I like to keep a local patch of it, as follows: "git diff > works.patch"

Later on, you can apply it if necessary with "git apply works.patch".

[+] _blz2|1 year ago|reply
Read once here, the best cheat sheet is one you create yourself. In my case, with fish shell or bash history search with fzf, I've effectively created a cheat sheet of commands I frequently tend to use with working examples. Seems to be working for me so far.
[+] rswail|1 year ago|reply
Git has its quirks, but the underlying model is good.

There's some naming problems, like I just had to explain lightweight tags vs annotated ones to some newbies.

The lightweight ones should have had a different name, like "bookmarks" or something.