Last week Shamus Young has decided to open source his excellent proof of concept, procedural world generation project codenamed “Frontier”. This is actually quite exciting as there is a possibility that someone will clean it up, and manage to tweak it into something with actual game-play. This is not what I wanted to talk about though – I wanted to talk about what happened immediately before this event.
Shamus asked the community where they would like the project to be hosted. The answer was a no-brainer – everyone in the comments agreed that Gitghub was beyond a shadow of doubt the best place to put it. And so, Shamus downloaded git and attempted to get the project under source control and out on the web. And then this happened:
Created an account. Created a repository. Installed Git locally. Followed the directions to set up git locally, which includes typing stuff into a Linux shell, which is trivial if you know what you’re doing and utterly, utterly mysterious if you don’t. Created ssh key. Set up a local repository. Added files meticulously one at a time from a list of hundreds of files because the Git GUI just lists all files and I don’t see how to filter for JUST source files. I hit commit and… nothing showed up.
His mounting frustration very apparent, and I know exactly what he is experiencing. This was more or less my first encounter with git too. It is not straightforward. Github is not helping either, because it does not tell you that you can bypass the ssh key requirements by simply using https:// instead of git:// when setting up the remote repository. If you plan to be using git and github a lot, then generating and uploading the ssh key is definitely a good idea. But for a one-off project like this, it is a lot of unnecessary hassle and a significant hurdle for new users to overcome.
There is another significant issue at play here – Shamus, like many users new to distributed source control sees familiar words like “commit” and assumes they work the same as in centralized repositories. Naturally they do not, but it is sometimes difficult to ascertain that by glancing at the official docs. Because, you know that’s exactly what we all do when trying to get a new tool working. We glance at the docs, we we use them at all.
I remember my own confusion – when I was starting with Git, I wanted a quick and easy, one sentence explanation of what the fuck is the distributed thing all about, and how will it make my life difficult.
This was supposed to be a quick & easy thing, and I’m now 40 mins in, I’ve got Git infrastructure spewed all over my computer and I can’t get it to do this very simple thing. I’ve used source code control before, and it was always pretty straightforward. Even thirteen years ago, I never had to type crap into a console window to perform simple tasks. Is Git only for people who understand Linux? (The front end is all friendly and Windows-like, which is what led me to believe I’d be able to do this. If it started with a console window I would have realized this was for someone with a different skill set and looked elsewhere.)
I can relate to this too. When I first installed Git on Windows I tried to use the default GUI. I say tried, because I have never actually managed to get anywhere with it. The UI is so obtuse, confusing and convoluted I could not wrap my head around it. Forget user-friendly – Git GUI is downright user-hostile.
Fortunately, I discovered Tortoise Git which works more or less the same as the SVN equivalent. So I was able to hobble along and sort-of use git (but not really) until I realized that it is much easier to use the command line version. Shamus was not so lucky – the UI defeated him. This was a complete usability failure.
Granted, part of the problem lies on the side of the user. Git was a tool made by Linux geeks, to solve an array of very complex issues involved in massive collaboration projects such as Linux kernel development. It was not made to be user friendly, forgiving and nice. It is a tool deeply rooted in the Unix philosophy and designed to be what a high end power tool is for a craftsman – a precise, powerful and flexible instrument that nevertheless requires some skill to use.
The lack of training wheels is more or less by design. You would not put training wheels and streamers on a racing bicycle, would you? It would defeat the purpose. For a tool such as git, the user is expected to put in some time and effort up-front to understand the tool, and then recoup that time in productivity later.
I have no idea what Git wants or how it works. I don’t see ANYTHING that tells me how to push changes to the remote repository. If doing simple things like “submit changes” means using a terminal window, then… damn. What year is it? I know you Linux coders have a high tolerance for this sort of thing, but damn – there are better ways of using a computer these days. Case in point: If I had a menu, I would be able to work this out for myself.
I have tremendous amount of respect for Shamus. His projects such as the Procedural City or Frontier are a standing body of evidence that he is a highly skilled, apt and capable individual. He failed not because of ignorance, but because he has mistaken a steep learning curve for bad design and called it quits early on. This is usually a good strategy – investing time and effort in learning a tedious, broken tool makes little or no sense. You spend a lot of time learning it up front, and then a lot of time fighting with it every time you need it to do something. It is a waste.
But, git is actually well designed and finely tuned tool. The crudeness of the Windows GUI is not really a problem with Git itself, but with the implementation of the Windows port. It does not condemn Git or Github. Unfortunately Shamus failed to look past that.
I agree that the default GUI in MySysGit is really atrocious. It also doesn’t help that a lot of official Git and Github documentation is overly dense and needlessly complex. Here is my attempt at an easy from zero to github primer for someone who just wants to set up a repository, push their project online and forget about it.
Why Command Line
Believe it or not, the command line is the most efficient way to communicate with your computer. It is the closest thing we have to actually talking with the machine, in the way that is exact and precise (and not fuzzy pattern matching like Siri does with speech).
When you are working on a command line, you issue precise directives, whereas a GUI is like a big menu board from which you pick your options. That board has to be designed for each application, and feature every possible option, for every circumstances. If the GUI designer hides advanced options for the sake of simplicity, power users will loose productivity clicking extra things or opening extra dialogs impacting their productivity. If they show too many options, the interface might become to dense and to difficult to navigate and use efficiently. Command line programs usually have sane defaults and then use arguments for extra stuff. So if you need more options, you just type more – and you only include as many as you need. You work at your own comfort level.
With Git, you will need to memorize about five basic commands which will cover 90% of the things you will be doing on a daily basis. The remaining 10% comes into play when you want better organization, when you mess up, or when you try to merge things that were not designed to be merged. In those situations things get hairy and ugly whether you use a GUI or CLI so it really makes no difference. In my experience GUI’s tend to exacerbate and obfuscate these sort of issues more than they help.
If you don’t believe me, go download Tortoise Git and use that. It’s much better than the default GUI of MySysGit. But keep in mind it is a crutch.
How Git Works
If you have ever used a centralized source control such as Subversion, you are probably used to something like this:
Everyone shares the same central remote repository. People check out code, modify it on their computer, an then check it back in. When you are working alone, this usually works quite well. If you work with bunch of other people, the code they check in, may conflict with your changes. When that happens things get hairy and you (or the project maintainer) will need to massage the code from both sides to make it fit before it can be committed and saved.
This is a big issue on large open source projects where a ugly merge can prevent everyone from checking code in. While it can be alleviated to a degree by use of tags and branches it never really goes away.
Git (as well as Mercurial and other distributed source control tools) were designed to resolve this issue by designing the system like this:
This is sort of how Github works. Everyone has their own public repository on Github. If you want to collaborate on a project, you “fork” it and you get your own, personal copy. But you don’t usually check code into the online public repository like in centralized systems.
Instead you make another private repository locally on your computer which is an exact clone of the public GitHub one. Then you modify and check in your code into that one. Then at the end of the day you can sync the changes to your public one by issuing a “push” command. Your work does not touch the original repository that you forked. But the owner of that repository can “pull” in your changes at any time. Then it is up to them to deal with merge disasters.
This is the beauty of distributed source control – you never need to worry about conflicts, unless you want to, and said conflicts will never prevent other people from working.
From Zero to Github in 5 Steps
Earlier I mentioned that there are 5 git commands you need to learn to get your project onto Github. I was not joking. Let me put my money where my mouth is and prove this:
Step 1: Create a Local Repository
You start by opening the shell and navigating to your project folder. On Windows you can just right-click on that folder and choose “Git Bash Here”. Then you type in:
git init
Boom, now your folder is a git repository. Yes, it’s that easy.
Step 2: Add Files
Next thing is to tell git what files you want to be committed:
git add .
This will put all the files in the folder under source control. You can also add files one at a time (by replacing the dot with a file name) or use wildcards (eg. *.cpp, or *.py).
Step 3: Commit Added Files
Now we commit our changes into the local repository:
git commit -m "First commit"
Note that Nothing goes to Github yet. Your changes can’t be seen by others. But you just made a snapshot of your code. You can easily roll back to this state at a later point and etc.
Step 4: Add a Remote Repository
This is the point where you go to Github and create yourself a project. then you do this:
git remote add origin https://GitHubUsername@github.com/GithubUsername/Your-Project-Name.git
This basically telling git “Yo, git – I want you to become aware of a remote repository on Github, which I will from now on refer to as ‘origin’ and it’s located at this address”. You notice I used the https rather than git: or ssh: address. Why? Because this is easier – you don’t have to mess around with keys this way. Git will simply ask you for a password when you “push” to github.
Note that I used https:// and not git:// like Github recommends. Why? Because this lets you bypass all the ssh key steps. What ssh key steps? Don’t worry about them. That’s my point – for now you don’t have to. Git will just prompt you for your GitHub password when it needs to authenticate and it is good enough for now.
Step 5: Push
Now, lets actually upload (or “push”) your code to Github:
git push origin master
Master is the name of the branch – the default one is always master, unless you have changed it. Origin is the nickname we gave to your repository in the last command. If everything worked correctly, you should see your files show up on Github.
Good news: we are done. Yep, that’s it. All it took was five commands and your code is under source control, and published on Github. You can usually accomplish this entire sequence in about a minute.
If you make changes to your code, and want to update the GitHub repository at a later time you just go back and re-use 3 of the commands you already know:
git add .
git commit -m "I made changes"
git push origin master
That’s it. That’s all you need to know to get started. Of course there is much more to Git than this – but you can pick up all the other useful commands later on (or not, if you don’t plan to use git often). Here is my personal cheat-sheet that includes the stuff I tend to use often.
In Conclusion
Command line is not scary. It only looks scary and intimidating because it is empty, and you can’t just intuit your way around it and wing. Source control is probably one of these things you don’t necessarily want to “wing” though. So perhaps it is for the best. Still, once you overcome the fear of the shell, you can create a repository and get it deployed in about a minute or two with five easy commands. It is not difficult – it’s just not trivial.
Seasoned git users – would you add anything to my list? What would be the sixth command you need to know right away? Remember to keep it simple for newbs. And don’t say rebase, because I don’t think someone like Shamus would have any need for it at first.
Do you sympathize with Shamus and his Git issues? Did you go through a similar phase when you first started using git? How did you overcome it? What made it all click and fall into place for you? Do you use a GUI, and if so, which one?
I never understood this approach of just throwing stuff at the wall and hoping it sticks. Why wouldn’t an intelligent person read the manual and understand how the tool works before trying to use it? I don’t mean reading and memorizing every single concept, but at least the basics, like what “commit” means on Git.
And if the manual isn’t clear, we have Google now! Searching for “git guide” or “understanding git” returns awesome pages written for many kinds of audiences.
I mean, consider your own blog post: it’s an awesome guide, but he wouldn’t have found it anyway.
And his comment of having to use the terminal, “what year is this?”, is he serious? The guy codes in C++, which is 30 years old by now; one would expect him of all people to realize that tools don’t necessarily become useless as they age. Yet there’s an irrational refusal to understand why people still use it, assuming instead they just “put up with it”.
Sorry for the rant. I guess I’m just sick of people complaining about the awesome tools they are given because they aren’t offered in a golden plate.
Wait, wait, wait… Git has a GUI?
Hey,
Just to say that I use SmartGit as a GUI for Git. This is the only one that I found clear enough and decent at doing things that are a bit complicated.
It’s normally paid for, but you can use the free version as much as you want, as long as the projects you manage are opensource. I think there’s actually some predefined handlers for GitHub.
Nothing will ever beat TortoiseSVN, but for something that’s not too simple (like the base Git GUI in linux), it’s not too bad.
@ IceBrain:
I know. He should. And yet, here we are. I find this sort of thing quite disturbing. Normally hearing such complaint from a programmer would immediately cause me to assume that said programmer is just a n00b complaining because he doesn’t feel like learning. But as I said – I’ve been following Shamus’ blog for years now and I know he is a clever fellow. Hell, I know there are some people who look up to him on that blog, so it disappointing me that he posted this tirade.
@ astine:
Well, not git, but MySysGit which is the go-to Windows port that everyone uses. It ships with a really shitty optional GUI wrapper which installs by default unless you un-check a box in the installer.
@ Gui13:
I have never used that one. Does it have any significant advantages over command line (other than being a GUI of course).
I was somewhat speechless after Shamus posted his Git rant. Seeing someone so intelligent and disciplined at programming get completely stuck on the relatively simple matter of source control was just baffling. The rant was sandwiched (roughly) between a post about octrees and a post about 3D noise; he obviously knows data structures, so he could grok Git’s internals inside of about 5 minutes. I was also frustrated, just like IceBrain, because he was sitting there in front of an awesome tool (Git and GitHub) and couldn’t appreciate it.
But, as IceBrain said, rather than spend time to learning it, he tried to cut corners by throwing things at the wall until something stuck, which backfired by taking longer to get nothing done. I think he wasn’t really interested using Git, just trying to publish his code the Right Way, so he saw no reason to invest time into it.
I was also surprised to see that he has no working knowledge of unix-like operating systems, as indicated by his total aversion to terminal work. I had thought he had some experience with Linux. I guess that explains his older rant about libraries — something any decent Linux package manager would mostly solve. More proof that a lot of people aren’t using Linux not because it’s not good enough, but because they’re simply unaware of how powerful it is. :-)
That being said, I have no interest in any of the Git GUIs. I think the command line beats them all. However, I do use Magit, an Emacs front-end, for the majority of my interaction. Maybe that counts as a GUI and I’m a hypocrite!
Well said. “This is the weapon of a Jedi Knight. Not as clumsy or random as a blaster; an elegant weapon for a more civilized age.”
@ Luke Maciak:
Hey, at least I made sure the icon should look nice! :-D
@ Chris Wellons:
I’m guessing Magit is probably much like Vim’s Fugitive that is a Vim wrapper around Git commands. I usually use it for the :Gdiff command that runs git diff and opens both files in side by side diff buffers, using full color and highlights.
And yeah – if you have read Shamus’ autobiography thing you can see he somehow bypassed the whole Linux adventure most geeks embark on around college time. Curiously enough, his wife uses Ubuntu apparently. So yeah, go figure.
Also, good job on improving the icon. :)
Hello,
first of all I wouldn’t say “you can’t just intuit your way around it and wing” about all that command line stuff. The shell you use nowadays is likely has completion. The commands themselves are named in more intuitive way, than the “where the hell in the menu is that bloody item hidden”. Furthermore, when I feel totally lost in “how this is to be done” I issue e.g. ‘apt-search source control’ command and always yield a lot of hints even without need to google.
Otherwise, the approach we all geeks are stuck with, is merely suitable for persons who get used with GUI. My wife, for instance, switched to Ubuntu two years ago and while she is absolutely lucky with it, she still doesn’t have the terminal window always running. Even the Unity’s “GUI as you type” interface is not so impressive for her as for me. And if there were not these guys who is giving up things which are not click-click-done—we were still need to dance around
mkdir /mnt/flashdisk && mount
woodoo.BTW, my sixth item in the list would be
git stash
.True, race bikes don’t come with training wheels, but I don’t know if that’s an appropriate comparison here. Vim is also a very sophisticated tool, but it comes with vimtutor which makes it much more accessible. I think git also needs something like that.
I know next to nothing about programming, but I use both vim and git for my LaTeX files. For me learning vim was a much more pleasant experience than learning git. Thanks to vimtutor I quickly understood the absolute basics and then I gradually discovered the more advanced featuers as I was using it. But git was really frustrating, and although I figured it out in the end I still find it very complicated and opaque. Still, I find it surprising that even seasoned programmers struggle with it.
@ Stefanie: It’s not so easy as you think. I mean yeah for small programs is walk in the park but when you get on to complex stuffs it just gets too hard. That’s why even seasoned programmers struggle with it at times.
William,
web designing bangalore
@ Alexei Matyushkin:
Yeah, the shell in modern distros like Ubuntu is quite a joy to use. When I jump back to my mac or to Cygwin on windows, I always miss these little niceties.
Btw, mounting flash drives via GUI actually works quite well on my Kubntu machine. It’s actually one of the things where I hardly ever use the shell – I just see a thing pop up, click on it and I’m set.
@ Stefanie:
Hey, I think you might be onto something. Maybe we need something like git-tutor. :) That said comparing git to vim is a bit unfair. Git was released in 2005 so it is still fairly young. Vim has been around since 91 and it was based on vi which was released in the 70’s. So vim is essentially a product of 30 years of steady improvement. It makes sense that user experience is better – it should be.
One more command for a git newb, “git status.” I’m not going to lie, I practically spam it (this is probaly because I don’t do things like put my git files source control and so my global ignore files are different every where). It breaks out the untracked, changed but unstaged, and staged files. It helps to show the schema git uses with files. I really enjoy the staging feature over the svn changesets, it’s more fluid and intuitive to me.
JFYI: http://windows.github.com/ was recently released.
Alexei beat me to the recent github client built for Windows, but if it’s anything like the Mac version — count me out. I have really fallen in love with SourceTree (Mac App), it’s beautiful, it works with Github AND BitBucket (it’s made by the team that makes BitBucket), and it’s very easy to figure out while remaining functional.
Speaking of which, I have been moving development to bitbucket from GitHub. Call me a Techno-Hipster, but bitbucket is cheaper (free, usually) — and equally awesome.
@ Alexei Matyushkin:
Yeah, I saw that. Little too late for Shamus. I wish he had waited a bit. :P
@ Travis McCrea:
GitHub is free for public projects and it has better community/collaboration features, hence that’s where the cool kids hang out. BitBucket has free private repos which is very nice, but less of a focus on community. It’s just a matter of taste I guess. That said, it’s easier to get exposure for your project on GitHub, seeing how everyone and their mom has an account there. :)
Features wise: They are even.
You are right that github has a bigger community but how often do you just randomly start searching for projects to fork? Most serious devs will have an account on both to make forking easier.