Git cheat sheet [pdf]
wizardzines.com
wizardzines.com
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).
I’m using git dc, but it seems ds may be my new one, haha.
In case anyone cares to browse or suggest their own: https://gitlab.com/Falimonda/gitrc
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.
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.
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...
For neutrality, 'annotate’ was another alias.
For the same number of characters, I have heard of "git glory" as a possible alternative.
[1] https://github.com/looshch/configs/blob/master/.gitconfig#L1...
The original commit will only exist for as long as git deigns not to garbage collect it.
I highly recommend Fork.
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.
I have only praise for Sublime Merge.
Seeing this cheat sheet really brings it to life.
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...
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.
The fact there are 5 different ways to do the same thing is BAD, not good. Have one well defined, documented clear way to solve a problem.
I don't know where I called anyone lazy.
I can't tell you how to do a single one of these things in git without looking it up. My years of experience with git is around a decade I think. My experience with Jujutsu adds up to about 3 months.
Sure, there are things that I would still have to look up how to do with Jujutsu; I don't know all of its features. I think the operations I know how to do with Jujutsu off the top of my head are strictly a superset of the operations I know how to do with git though.
I clone a repo. I make some changes to my copy. But then I want to keep my copy up to date with the original repo by stirring in all the updates that have been made lately to the original repo.
Seems like it oughta be simple, but git makes it mysterious. Will jujutsu make this possible using only simple, sensible CLI commands ? And conflicts will be nicely stored away for near-term cleanup ?
Inquiring minds want to know.
jj rebase -b @ -d branch@remote # rebase the branch of the current working commit onto the newly fetched commits.
Note that the way to do this with git is almost identical, but maybe not as obvious. In git I think this can be done with a single command though: git pull --rebase.
If this is not the state you want your repo to be in and I misunderstood, I'm still pretty confident I could get a repo in the state you want using Jujutsu quite easily :)
Edit: though also the git way to do this would kind of force you to deal with cleaning up conflicts immediately, whereas with Jujutsu you can put off conflicts indefinitely.
That having been said, the team is really good at engines so the software is quite good at doing what it's supposed to do.
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.
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.
I used to think Mercurial had a better UI but I changed my mind after taking the time to understand Git. Mercurial does have nifty features but Git's way of working isn't hard or especially counterintuitive. You must learn the terminology to properly understand it, but after that it's smooth sailing. Git actually has fewer moving parts than Mercurial, as there are less extraneous features. Instead of 3 or more categories of "branch-like" graph structures like Mercurial, you get branches as refs in Git. Every named leaf in the commit graph is a branch or a tag, and those have simple properties. There are surely git plugins to add more metadata but you don't really need that.
Git too has a web interface by default: https://git-scm.com/docs/gitweb Of course there are many Github-like solutions specifically catered to hosting repos and entire project workflows with Git too.
It is kinda nice to not be able to accidentally lose a branch even if you're a low-skill Mercurial user, and that is the main selling point for most people. On the other hand, low-skill Git users lose stuff often. It's actually really hard to lose committed stuff in Git because of the reflog, but the low-skill users never heard of that and you can really have a hard time explaining it to them. The other big complaint is about `git reset` and its various incarnations. People really don't take the time to understand what it does with its various options, and when they delete their changes accidentally they blame the tool.
This promise never held to me. I know the terminology and “how”, but it never got clear in my mind how to express day to day things which aren’t clone/add/commit/push. It’s just bad unmemorable ui that is both cumbersome to use and reason about.
I do have trouble remembering things but not like this with any other tool. For example, with ffmpeg and magick I could make them work without a manual. With git I can only damage things irrepairably.
My advice to get over the hump you're on is to commit more often, check the status more often (`git diff [--staged]` and `git status`), and make sure you're branching or tagging enough to not lose commits. Then work on how to edit commits with `git rebase -i`. You can use rebase and cherry-pick to eliminate any unwanted commits or branches easily (notwithstanding conflicts, which are another critical thing to learn). If you feel like you messed up, you can almost always `git reset --hard` to the last commit you were on. If you forgot which commit you were on, there's the reflog. Generally, to be good at Git you have to take a few hours to learn it. It differs from the other programs you mentioned because there are different problems you can encounter at various points while using Git, whereas those other ones just succeed or fail and don't usually fail in unrecoverable ways (you just run them again until you're satisfied with the output). You can iterate on modifications to your commit history with Git but that is trickier and riskier.
There are many excellent Git tutorials online that explain everything an ordinary user needs, including rebases and the reflog. I think Github has one. Maybe that's what you need to figure it out, in addition to practice of course.
In git there’s always “foo”, “bar --frob” or “baz :QUUX -j” in a set of logically related operations, and neither of keywords make sense. Also every generation of git had its own ui ways, so it’s very hard to learn if it’s e.g. some reset/checkout incantation or just restore that you wanted, because when you refer to google, it never knows it’s not 2015 anymore. Some humans can’t learn inconsistent badly named things, I’m one of them. I can remember, but to actually understand I’d have to understand Linuses mind’s inner machinery, which is alien to me.
I think most of what you need is actually on this cheat sheet, so maybe all you needed was a reference.
And this complexity was literally from the first trivial thing I checked, I wasn't looking for it for hours to gaslight anyone here. Git is nice and fast as a core program, but its ui, documentation, compat and informational ecosystem are just poor.
Hare-brained. (Hares are not supposed to be very smart animals.)
Of course things were run afoul when Tridge started reverse engineering the bk protocol/datastructure but frankly the need to switch away from bk was a bit self-inflicted from what I could tell.
Throwing all in one bucket necessarily leads to confusion. Sure, there were and are FOSS zealots and Linux zealots and there is an overlap. Linus Torvalds himself however is a very practically minded guy who clearly expressed that he would use proprietary software if it would suit his needs better. He got a lot of heat for that stance, as some Linux kernel developers happen to be more ideologically pure. No need to warm that battle up.
(oh, BTW, BitKeeper is FOSS since about 2016)
In newer versions of git the cost of adding new subcommands is reduced and they've started adding more specific commands like git switch.
Git is very simple. It is built on just four concepts: blobs, trees, commits, refs.
-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. 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. 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!Shouldn't this be: `git rebase -i HEAD~5` ?
Assuming you only want to rebase linear history.
https://stackoverflow.com/questions/2221658/whats-the-differ...
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.
- 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.
https://martinvonz.github.io/jj/v0.17.1/
I think even Linus thinks git has a shitty UI. JJ has an amazing workflow.
Other than playing around with it, I haven't really used it in anger though, so...
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.
The phenomena you describe is known as the Curse of Knowledge [1]
Wikipedia gives an example: A knowledgeable professor might no longer remember the difficulties that a young student encounters when learning a new subject for the first time. [2]
> Twenty minutes later he returned, smiling, and began: "Yes, it is obvious that..."
A professor's main job is not to teach. It's publishing and getting funds into the university.
I work at a company where every developer uses Sourcetree, a GUI for Git. I don't really have a need to remember Git commands (and what arguments they take) anymore after using a GUI. For me, it is sufficient to know what Git commands do without knowing the semantics.
Once the mind had bootstrapped itself to a concept, it is very hard to empathize with your past self unless you took cares to document the difficulties while still in the confused state, articulating as much detail and as many fallacies encountered as possible.
I always liken it to Wittgenstein's analogy -- don't throw away the ladder after having climbed up upon it!
Squashing, dropping commits, rebasing. Even interactive rebase can be done in a few clicks.
I sometimes pop up IDEA to do some non-trivial cleanup in a repo. Even if relatively fluent with the command line, it saves me a lot of time.
As someone who has worked on developer tooling, including building a custom git client at a former job - yes.
Most people learn a few specific workflows not conceptually how things work under the hood.
Visual editors like GitKraken, Submlime Merge, Sourcetree, etc, have made this much better but there's still a big gap.
Basically, developers rebase all the time on their own branches, and rebase over their target branch (fixing conflicts) so that the PR is fast forward.
Agree on the git model thing, I feel like I have a reasonable idea of how git functions under the hood now, so I can figure out what most operations should do, even if I haven't used them before.
But writing software, tracking your changes, being able to back out your changes and getting your changes integrated into a code base should be as low activation energy as possible to be productive.
But again, git wasn't created for "you and me", it was created by one guy for his project, the fact "mere mortals" are using it is kind of our fault.
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!
I half a day later I gave up. Never got to install magit.
I've since switched to Vim and happily use git at the terminal prompt. I doubt that will ever change as the interactive interface of various Git commands has improved.
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.
`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.
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.
Later on, you can apply it if necessary with "git apply works.patch".
I use stash too, but for different purposes. For instance, when I'd like to quickly change branches to fix a bug/issue and then come back to my stuff. Sometimes, I use stash for resolving potentially complicated pre-commit merges as well.
For a more robuts method, you could also just commit (without pushing of course). Then, you can do "git reset --hard HEAD~1", and you have a pre-patch env ready for more work. When you need to re-do your commit, you can check reflog to get the ID.
Either way is, to me, an easier way to achieve the same result as patches.
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.
is also super powerful to put a series of commits on top of a new parent when history has changed.
That happens with PRs and squash merges quite often.
I literally spend half an hour the other day having an argument with chatGPT about how I could find versions of a file that contained a specific string. Guess I should have asked for commits and not versions of files.
[1] https://github.com/looshch/configs/blob/master/.gitconfig
Atlassian Sourcetree in theory works with Hg (because Atlassian's Bitbucket used Mercurial as their primary version control system before moving to git) but SourceTree is Windows/Mac only, there is no Linux version for some strange reason.
Trying to run SourceTree on Linux via WINE fails because Sourcetree can't be installed with the 'Administrator' user and recent WINE releases have (accidentally?) removed the ability to run a WINE program as a non-Administrator user.
I haven't personally tried (yet) to install Sourcetree on a Windows machine and copy the directory over and try via WINE, but it's on my list to do.
I haven't used it myself but I might for a solo project I'm involved in right now.
A good read (not my article, linked from the Fossil site):
In my mind Git solves a different problem that Linus Torvalds was facing: many people working in parallel with only some of the ideas pushed upstream, but many people wanting to make changes and easily being able to move forward to the latest changes from upstream.
My extremely opinionated view is that most people should use Subversion unless they have a very complicated team structure. And that means every solo dev working by themselves should not complicate their own lives by using Git unless they are really comfortable with it already.
Why would a solo dev choose to use a client-server version control instead of one that works fully locally?
You can ask Subversion to create a repository anywhere you like in the filesystem.
Pretty much what is listed in the OP cheat sheet.
As a former member of Meta's source control team, I believe this with pretty high confidence -- many of the workflows that we rolled out within Mercurial/Sapling, and caused it to consistently be the most loved developer tool at Meta for many years based on surveys and interviews, have been adopted and improved by Jujutsu. See my testimonial, the first one at [2].
[1] https://martinvonz.github.io/jj
[2] https://martinvonz.github.io/jj/latest/testimonials
(Disclosure: I'm obviously biased towards the Jujutsu workflows, and its creator and I worked together on Mercurial. But I like to think that this specific belief of mine is pretty data-driven, both via stated and revealed preference.)
This is the message I see.
> The author made this story available to Medium members only.
> If you’re new to Medium, create a new account to read this story on us.
https://webcache.googleusercontent.com/search?q=cache:https:...
If your mission is to make hard topics easier to understand, why are you using a hard-to-read font whose only purpose is to make the cheat sheet look folksy?
to update a branch while you're on another branch
Thanks!