I recommend this site to people a lot, it's nice. What's not nice is people not being aware that Git comes with a graphical history viewer for your actual repositories, gitk, which should really be people's default go-to. (There's also log --graph if you want ASCII art, but an actual GUI is quite a bit better. There's also other GUIs that display the information gitk does, of course.)
Git is truly the Dark Souls of version control systems - that is, it's wonderful and masterfully crafted but it has attracted this misguided cult following which spreads misinformation about how intractable and hardcore it supposedly is. Dark Souls doesn't have forge sites deliberately (?) adding to the confusion (maybe all those youtubers...), though.
Try also "tig" which is something in between git --log and gitk.
Also, I firmly believe that git is very simple if you use it right. I'd you are deep in the manual with exotic commands and flags it's most likely your own fault.
Edit: forgot to add that saying git is not complicated always gets heavily downvoted on HN. So goodbye digital karma...
Git's data model might be simple, but the commands sure aren't. Compared to Mercurial the UI is a mess, although better than it used to be, which isn't surprising since each command initially kind of evolved as a separate program rather than being designed as part of a coherent user experience like Mercurial.
I find that Git can usually do everything Mercurial can, but it does involve those "exotic commands and flags". For example, the equivalent to
hg id -i
is apparently
git describe --abbrev=12 --dirty=+ --always
which is not exactly obvious, not even if you read the manual. Stack Overflow also suggests alternatives[1] using "git log", "git status" and "git rev-parse" which do similar but slightly different things and accept similar but slightly different options.
What about listing all filenames from all commits – "hg manifest --all"? I'm sure it can be done, but I'm equally sure it involves exotic flags.
That's kind of a misleading comparison. It takes that many characters to exactly reproduce the "hg id -i" behavior because hg chose a certain set of defaults that git didn't happen to choose. What if as an hg user I want the first 16 chars of the commit ID and don't want the "dirty +"? The hg command quickly starts to look uglier.
If you just want the current commit ID in git it's just "git rev-parse HEAD". Which is still longer and uglier than "hg id -i", yeah, but it's a fairer comparison.
True. My point is that Mercurial has a more coherent set of commands that usually, in my experience, give you an obvious way to do obvious things.
Git has (although it's gotten better!) functionality spread haphazardly across different commands, and many commands can perform several seemingly unrelated tasks depending on the flags. There are lots of command to give you the hash of current commit, all with different combinations of bonus features, and in this particular case we use describe (which really seems to be for finding tags reachable from particular commits) because it happens to support the right combination of features.
(Perhaps I should mention that I'm currently migrating to Git. Git is fine. Many things are better than in Mercurial, just not the UI.)
TBH I'm not sure I'd ever heard of "describe" -- I'd always used rev-parse to get a commit ID. But now that I'm trying it, it gives me a branch/tag name rather than a commit ID (either bare "git describe" or with the other arguments mentioned above). So...not really sure?
It is simple and powerfull but not intuitive. I work a lot with biologist and I explain it as a lab journal: for a lab journal there are, depending on your company, many strict rules to follow, to keep it "valid". For example, changes need a date stamp, people need to sign off on your journal every 3 months. You need to number the pages and keep an index to show it has not been tampered with, etc.
Like many things in the computer world one starts out feeling that something is overly complex and then slowly one realizes that one would have designed a system just like it is now, given the opportunity. Realizing this has made me stop judging new tech until I try it for some time. Also, when many people use something and I find it to be overly complex, I try to reserve judgement and spends some hours at least to really try something. Although this does require some problem to be solved (a concrete target), at least for me.
The best way I found to learn git is to read the first 3 chapters of Pro Git. Yes it's a pain, yes you're going to have to sit through the "distributed source control" speech again, but the enlightenment of realising why it works like it does is great.
When you realise it's nothing more than commits and a bunch of special labels it starts to make sense.
EDIT: Meant to add that sites like ohshitgit might help in a crisis but you're only a few hours reading off working out WHY those things work.
> Git comes with a graphical history viewer for your actual repositories, gitk
Well, sometimes it does, sometimes it doesn't, e.g. on macos it doesn't.
> gitk, which should really be people's default go-to
That's a matter of preference. For instance, I've been recommending Magit to all new starters (quickly installing spacemacs as a shell for that) and it's been working out great so far.
See, there's literally thousands of "git guides" and maybe dozen of "visual guides" (not to mention cheatsheets, "handy aliases" lists, etc.) and they keep coming, which begs the question — why are they there in first place? How come existing ones are not enough?
> Git is truly the Dark Souls of version control systems
Yeah, but in a bad way. In my 10-years-experience with DVCS, Git requires orders of magnitude more attention than any other (D)VCS (except, maybe, monotone), offering nothing in return.
> Git is truly the Dark Souls of version control systems - that is, it's wonderful and masterfully crafted but it has attracted this misguided cult following which spreads misinformation about how intractable and hardcore it supposedly is
To be fair, From Software definitely plays into the "hardcore" image of Dark Souls with their marketing.
Do you think we'll ever get "Git: Prepare to Die Edition"?
An introduction such as this, should also explain about ways of working with git and not just explain the commands. I still remember the first time when I started working with git, that I was warned never to use rebase, because it could be dangerous. It was only when I moved to another working environment, that I learned how to use it, and only about five months ago that you can add --rebase with the default pull button. But still I find myself using Git Bash shell often.
It took me also a long time to learn that origin was the default remote and that you can add more remotes and that you can also push to a repository on a USB drive.
I have been working with git for about four years now and it is only in the past year that I feel a little comfortable with it. But still when I look up a git command, I am overwhelmed with the shear number of options. On the other hand, I am still surprised by the number of commands I have to type to do something as simple as rebasing my uncommitted changes with the latest commit from origin. Or what you have to do to squash your commits on the current branch since your lastest push to master (or develop).
Git is like a toolkit with relatively small and intricate tools, that often baffle beginners that only want to perform a limited number of operations according to a certain style of working.
I understand there's a whole lot of FUD behind rebase, but I still don't like it. To me, a project's branch structure provides a history of how it all went down, and when I'm trying to hunt down a mysterious change in the code, it's all information I can use to figure out exactly why a certain decision was made, and whether it was made on purpose or by accident.
I think rebase and squash go together in terms of what you want to get out of the VCS. If you want a clean history, where every commit represents a complete feature, with the knowledge that you can check any commit out and expect it to work, then squash and rebase are your friends. If like me, you want to understand the history of the code, warts and all, then merge is the way to go.
Also, I find I can achieve most of the benefits of a rebase workflow by just defaulting to git log --first-parent.
I really doubt that it's ever necessary to understand the intricate history of each and every developer working on a codebase to be able to track regressions. You're not Poirot.
History is an artifact of development and if it's worth keeping then it's worth maintaining. Rebasing serves to clean up the history ready for archiving (ie. merging to master), giving you a long linear line of commits that is possible to bisect to quickly find the source of regressions.
You do want to curate topics with interactive rebase, but you probably shouldn't want to destroy useful information by making everything linear. This is a common and I believe misguided thing people do when they don't know about e.g. gitk (which comes with Git, although your OS packager might split it out).
It certainly doesn't aid the bisect command at all. It might hinder it (e.g., a whole series becomes bad because you rebased it off a release tag onto some random point; bisect would pinpoint the merge if you had merged it, but you destroyed useful information so it can only pinpoint one of the diffs).
As you say, you definitely don't want to archive every weird developer fumble during development. That's useless noise that makes the history unreadable.
Yep, architecture decision records (ADRs) for the win. Just next to your README file in the repo.
But big projects seldom use rebase. This is because it's quite hard to `git revert` an entire change from two weeks before (change being e.g. 50 related commits).
Ever had a friend or editor help you with an essay? Often they’ll suggest cutting stuff out to make the meaning clearer or rewording something that was left over from an earlier edit.
I do a LOT of check ins — sometimes just for a few characters when, say, refactoring, as I want to trivially undo multi-file changes. Sometimes I do a half of implementing a feature, save, run tests, then finish the job, perhaps eliminating scaffolding erected to make the implementation work, vitally important at the time but would just end up as noise when someone wants to just see the new feature implementation.
So squashing that down to a few check ins can be more informative. Especially if the implementation took a few days so needed to catch up to the head of the tree a few times along the way.
> An introduction such as this, should also explain about ways of working with git and not just explain the commands.
Amen! Too often, and this isn't exclusive to git edu, there's too focus on features and not enough on benefits.
Saying "this is the command and this is the syntax" provides no context. Git is especially context sensitivity. Without seeing real life examples of _why_ and _when_ the how is meaningless and in turn forgettable.
I also doing understand why these isn't a solid and reliable UI. Maybe there is and I struggle to find it. How fitting? ;) The point being, git is a series of events (commits and merges), or across dimensions (i.e., other team members). It is, at very least, a three dimensional graph. Stuff that into two dimensions and then into a command line well that qualifies as elitism and jargon.
The idea behind the tool is excellent, and necessary. But how it's executed? In 2020? It feels too much like a fax machine.
This will save me a lot of time. I'm always hopping between branches on the single repo we use to stay in the free-tier. I couldn't find this in the Git documentation, but it works great!
I'm a little confused how re-cloning a local clone helps you compared to cloning the original remote repo. You can certainly have multiple clones of the remote repo in multiple locations on disk. To avoid name collisions, you can just not clone to the same parent directory, or choose an alias: `git clone <URL> <ALIAS>`.
However, if cloning your monorepo and switching branches takes a long time, consider `git worktree`. This set of commands allows you to clone a repo once, then keep multiple branches checked out at the same time, in different directories. See this, for example.[1]
I find that learning about the ways of working with Git follows relatively naturally after you spend about 10 minutes learning about how Git is modelled. (I created a visual tutorial about that a number of years ago: https://agripongit.vincenttunru.com/)
This actually looks pretty good. I've not seen it before. As someone who has always been the "git guy" at every place I've worked, I can't stress enough that the way to learn git is to learn how the DAG works and understand that git is fundamentally an append-only data store. If you can grok those two concepts then learning the commands is simply a matter of understanding what they are doing to the DAG. You'll also learn to trust git. No longer will you to do caveman shit like delete and reclone your repository.
That's nothing like the OP. The OP actually tries to teach you how git works. Your link gives people crappy recipes to copy and paste which teaches you nothing and only serves to reinforce the idea that git is "hard" and that you can't possibly understand it.
Eh, it can be handy to have cheat sheet like that if you're comfortable conceptually with Git but need to quickly change something and don't know the exact syntax. After all git is a tool not a lifestyle, sometimes I just need to get something done.
In learning git years ago, it took visual representations of branches for me to fully get (g)it. Sourcetree was the tool that showed me this, and really helped. This tool looks like a great intro to git for beginners, but also for more advanced users too.
I also like Sourcetree visualization, great way to explain someone .git (on high level) and great way to quickly have an overview of project/repos history.
You can visualize git branches with Gits built in viewer, gitk, which provides a SourceTree like viewer of all the branches. It's powerful and always available, making it a wonderful tool to rely on!
I recommend this site first and foremost to every one of our new hires. Each time it turned them from someone who was scared of branches & rebases, to someone who was comfortable with the tool.
I think it's the single best git tutorial out there.
I was trying to learn git few years ago. Nearly all articles start from command line and me being more of a visual person wasn't getting it. So I put some days in, found some visual resources (best of them are dead now) and wrote this[0] as an answer to my own question on quora back then. It's not very good but I have been told its helpful.
Going through the levels I find myself wishing I could explicitly use HEAD any place I could use a branch name. It seems like it just adds to the variety of subtly different ways of moving pointers around.
git branch -f master c0 <- named branch points to c0
git reset c0 <- checked out branch points to c0
git checkout c0 <- HEAD points to c0
I'm still not sure if these commands have other side effects, or if I'm abusing the model in some way. But I feel a disconnect between the git model as explained to me (commits and branches), my interpretation of the model (file changes and pointers), the results I want (change pointer target), and the git commands (branch, reset, checkout).
This is the tool I always show my juniors when I teaching them Git the first time, and recently one of my earlier juniors showed this one of theirs. :) It's that good of a teaching tool!
I'm hopefully waiting for a new and easier alternative way of version controlling. I don't have any idea how it should be, but git's approaches are so complicated, possibly because of it is designed for so complicated projects.
There was and it was called Mercurial. It was exactly the same thing, but designed by ordinary people (i.e. not those working on the Linux kernel). As such, it ended up having less market share than zipped folders with hilariously incrementing segments of numerals in their names.
It is okay that some tools require experience and knowledge to use them correctly/efficiently. There is often tradeoff between usability and functionality. I mean it feels good to master these tools and educate others :)
Most big companies (think Google, Facebook scale) use a mix of Perforce [0] and Mercurial [1]. BitBucket supported Mercurial repositories up until recently, when they got rid of it, so now there's no super easy hosted Mercurial solution.
> Google doesn't use Perforce anymore. It's been replaced with Piper, you can read about it in articles from about 2015 or so. Perforce didn't scale enough.
Sorry, that's not true. I have a few friends who currently work at Google and I talked about remote work with them just recently. They all confirmed that Google uses Perforce.
Once you have a decent mental model of git, it works well.
Using git with magit is excellent.
Before I had a good mental model of git, I would've been comfortable with flows like 'add, commit, push' (and the smallest amount of branching from that; 'checkout -b', 'pull').
-- I wasn't able to easily dig myself out of holes I got into if I made the wrong command.
Correction, over 4 years ago it was posted a few more times under the old pcottle.github.com URL. For some reason all those postings are not coming up in either HN's own search (at all) or Algolia's, unless you search by title in Algolia:
And its valuable every time. I learned of this today and already recommended to my colleague who is trying to learn git. Of course there is an xkcd about this[1]
Git is truly the Dark Souls of version control systems - that is, it's wonderful and masterfully crafted but it has attracted this misguided cult following which spreads misinformation about how intractable and hardcore it supposedly is. Dark Souls doesn't have forge sites deliberately (?) adding to the confusion (maybe all those youtubers...), though.