14 ms·
Git koans
- ctdonath 14y agoShort of me downing distressing amounts of coffee, could someone explain these please for those of us still trying to grok git?
- vampirechicken 14y agoGit is a journey, not a destination.
- pipboy3 14y agoit's a satire
- 0x0 14y agoIt's a list of pitfalls which are all too easy to fall into. The somewhat inconsistent command line interface / option / argument parsing in git can sometimes lead to very unexpected results.
- austintaylor 14y agoI'm not sure what Silence is about. My git-config-fu fails me. One Thing Well demonstrates how one command (git checkout), while it does do 'one thing well' (changing your working directory to match something in the index), can handle a wide variety of seemingly unrelated use cases. Only the Gods demonstrates how history can mean different things: commit parentage, which is usually immutable, and branch history, which is ephemeral. The Hobgoblin probably refers to the Emerson quote "A foolish consistency is the hobgoblin of little minds." The Long and the Short of It is about how git accepts `git --help command`, `git command --help`, and `git command -h` but `git -h command` returns an argument error. A theme here is that git does not try to anticipate your workflow. Its commands and options are named based on what they do, rather than how you should probably use them. This makes git a very powerful tool, but with an interface that is often counter-intuitive.
- kzrdude 14y agoEach git command is a designed tool itself. Others expect it to be 'git' to be the wholly designed tool as one unit, but it's a toolbox.
- lelandbatey 14y agoJust to explain "Silence": Apparently, git does not allow you to alias default git commands (like "pull", "push", "commit", etc) to something else. In the given situation, a user is trying to alias the default "pull" command to "pull --ff-only" so that pull will not automatically merge changes and will only fast-forward. However, since git does not allow you to alias default commands, when the Git Master runs "git pull" it ignores the alias entirely and does a normal pull, and in so doing merges changes. The student is confused, but eventually figures it out.
- pilgrim689 14y ago> pull = pull --ff-only From "git --help config": "To avoid confusion and troubles with script usage, aliases that hide existing git commands are ignored." > “Use git checkout.” This is just a jab at how "checkout" does too many different things. > “I have a historical record of a merge commit with two parents. How can I find out which branch each parent was originally made on?” Git doesn't let you do this. > “Surely some of these could be made more consistent, so as to be easier to remember in the heat of coding?” Git commands can be inconsistent. > “git -h branch“. This command tells you nothing about "branch" (throws error), whereas "git --help branch" launches the browser at git-branch's manpage. This goes against what people usually expect (that "-h" is just shorthand for "--help".
- kzrdude 14y agoBut you should recommend 'git help', i.e. the help subcommand, since that's what git refers to on its own.
- herdrick 14y agoHe's criticizing git.
- kevingadd 14y agoThe 'Only the Gods' one seems weird to me; maybe I just don't understand Git well enough, but it seems like that one's just a case of failing to understand what a branch is. A particular commit isn't made 'on' a branch, so to speak; it's just a SHA hash that has a particular SHA as a parent. And then a branch is a pointer to a particular SHA. So there's no way to know which branch a commit originated 'on', merely which branches happen to contain a commit at present (because their current commit has the desired commit in its history). So, if you merge two branches together, of course you can not tell which branch a given commit originated on just by looking at history. That information was never in the history in the first place. I could see it being useful to track this in the merge somehow, though.
- pilgrim689 14y agoAlthough in implementation, a commit is not done on a branch, for the user, that is precisely what happens. You checkout a branch and you do a commit while on that branch. Thus, to the novice, it might be perfectly normal to expect Git to tell him what branches the commit was made on, even though that makes no sense from Git's point of view. I've never had that use case (knowing what branch a commit was made on), but if many people need it, surely explaining to them how Git works doesn't make Git any better for not being able to provide what the user needs.
- philwelch 14y agoBranches are just mutable pointers to commits. You're imposing a mental model onto Git that simply isn't present. Git is revolutionary, in part, because instead of asking "what's the mental model we want to emulate and then never mind if that matches the implementation", they gave developers credit that they can understand a handful of simple concepts and made the actual design and data model as simple as possible. Programmers know what pointers, SHA-1 hashes, and DAGs are, so just use them.
- aidenn0 14y agoMaybe Linux kernel devs deserve that credit, but it's becoming increasingly clear that developers as a whole don't deserve that credit.
- peterwwillis 14y agoSometimes I feel like Git is an elaborate troll by Torvalds. Doing my taxes is more intuitive.
- colinhowe 14y agoHas anyone made an alternative interface for git that tidies this up without drastically changing how you use git? Or would this condemn someone's sanity to the graveyard?
- tootie 14y agohttp://mercurial.selenic.com/ http://mercurial.selenic.com/
- varikin 14y agoThis may seem like a joke, but having used Hg a little bit, I do think it has a superior interface. The error messages are clear, the commands are intuitive. The command addremove is genius. But I still use git because I already grokked it before I learned hg.
- syncsynchalt 14y agoI learned hg before git and the experience of switching to git was shockingly bad. I'm comfortable in both now and the big thing I'd miss if I went back to hg would be git stash (and I'm sure there's a hg plugin for it).
- the_mitsuhiko 14y ago> I learned hg before git and the experience of switching to git was shockingly bad. I'm comfortable in both now and the big thing I'd miss if I went back to hg would be git stash (and I'm sure there's a hg plugin for it). What about the index? Or the branching (bookmarks kinda work now I think), or the better remote management?
- tootie 14y agoI personally hate the index. It gets in my way far more often than I actually make use of it.
- speeder 14y agoI don't understood the suicidal git thing... Also of course I had to test the help commands! git branch --help opens man git branch -h throws those short commandline help summaries. Interestingly, -h does not mention -h itself or --help, so the only way to know that --help exists, is someone else telling you, you will never find on your own.
- deleted 14y ago[deleted]
- LeafStorm 14y agoOr by using every other Unix command ever. (Disclaimer: This is a hyperbole.)
- thedufer 14y agoIn every other Unix command ever, -h is the same as --help. Having used -h, I would never try --help if I was looking for something different.
- damncabbage 14y ago-h is not a valid option. You could put --floogahbar in there and it'll give you the help by way of response.
- __david__ 14y agoActually, "-h" is not a valid option on "git", but it is on "git branch" (somewhat confusingly). Try "git branch -j" to see what happens when you pass a bad option. In particular, try that when your cwd isn't a git repository.
- syncsynchalt 14y agoThe 'suicidal' example was git -h branch: $ git -h branch [blargh]
- mpyne 14y ago> Interestingly, -h does not mention -h itself or --help, so the only way to know that --help exists, is someone else telling you, you will never find on your own. I've found the --help option on probably a dozen commands without ever being specifically told that --help was a valid option. If you have trouble discovering it you might want to look inward, at least for that particular well-known option.
- LVB 14y ago'git' alone tells me to 'git help <command>' for help, which I've done dutifully ever since. That is, until I too was enlightened a few minutes ago with 'git <command> -h'. Thanks, Master Git!
- giberson 14y agoOne Thing Well: The command of all these seemingly different action is the same, because all of these seemingly different actions are actually the same. The Long and the Short of It: -h is not a valid argument. Passing -h therefore results in providing usage information.
- the_mitsuhiko 14y agoA lot of these are just plain wrong though or have a good reason and it makes me sad because I know Steve Losh uses a lot of Mercurial which I think has a much worse UI. 1. Silence: you can't alias built-in commands — for good reason. You don't change the defaults of commands, that's just going to cause problems with scripts. Why is it ignored silently? For starters because new git versions can add a command that would conflict with your config that came from an older version. You can trivially see that an alias is ignored by just adding ``--help`` to the command and it won't show you the alias. 2. One Thing Well: I fail to see the problem with that? All of these do the same thing. They check out a revision. With the exception of branch creation which is actually not a feature of `git checkout` but `git branch`. There is just a convenience operation on `git checkout` that also changes branches. The better question is why branches in mercurial are called bookmarks :P 3. Only the Gods: thankfully you don't know which branch something came from. Mercurial fucked me over more than once where I accidentally pulled a patch that came from a named branch that was conflicting with one I already had (you would not believe how many people name their branches "bugfix"). Mercurial's named branches are among the stupidest idea in software maintenance. 4. The Hobgoblin: these are all different commands. "How can I view a list of all tags": that's not what all tags is, that is "what's the list of tags I know locally". In mercurial you can't even figure that out properly because depending on the branch you're on you get different defined tags since tags are stored in the tree. Git's tag system is much superior to that. "How can I view a list of all branches": that's a question you will never ask because it's the wrong question. A branch could show up multiple times. The correct question to ask is "How can I view a list of all local branches?" `git branch`, the second question is "how can I view a list of all remote branches?" And for that the answer is `git branch -r` or `git branch --remote` which makes a lot of sense in my mind. "And how can I view the current branch": Same way you show all branches, just `git branch`. Shows you your current branch as well as all other branches and neatly colorizes it. `git rev-parse` is a command you really never have to use unless you script something. Yeah, some could probably more consistent. The odd one out are `git submodule` and `git remote` which are sub commands instead of using parameters to remove/modify them. That being said, you rarely need to use those. In direct comparison with hg, git's UI and functionality is a present from god. I'm pretty sure hg only has a better UI reputation because git's UI used to be pretty bad. Now however? Pretty sure it wins over hg hands down.
- ozh 14y agoThe best part of this article IMO is the scrolling header on the left hand. Nice touch.
- imissmyjuno 14y agoAgreed. Reminds me of the list headers in iOS, e.g. in the Address Book.
- josso 14y agoReally annoying on an iPad while zooming in on the text.
- js2 14y agoGit commands are not consistent. This is a result of it growing organically, and having a maintainer who strongly values backwards compatibility. But you know, having used git for years that doesn't bother me. Let me explain. Git is conceptually straightforward[1]. It is difficult if not impossible to discern those concepts from its baroque CLI. So learning git from its built-in help and/or man pages is suboptimal if not a complete waste of time. Either read the Pro Git book[2] or pop the hood[3]. Then the inconsistent CLI is no longer a big deal. If it were, someone would have come up with a new porcelain (high-level CLI) that would have taken hold by now. And no one really has. There is Easy Git[4] but I don't know anyone who uses it. And really, I see git as not much different than Unix in this regard. Unix commands vary widely in their usage. Does knowing awk help with sed? cpio and tar? wget vs curl? Eventually you understand concepts such as pipes, regular expressions, file descriptors, etc and you become familiar with the commands where you are able to apply these concepts, at which point does strict interface consistency between them matter? I dunno, but I started with both git and hg around the same time and ended up happier with git. Mercurial had the "better" CLI, but I found git was better at doing what I wanted. Before that I used clearcase, which has a very consistent CLI and yet I was constantly cursing at it. Or maybe I just have stockholm syndrome and I'd feel differently if I'd ever used plan 9. :) 1. http://tom.preston-werner.com/2009/05/19/the-git-parable.html http://tom.preston-werner.com/2009/05/19/the-git-parable.htm... 2. http://git-scm.com/book http://git-scm.com/book 3. http://newartisans.com/2008/04/git-from-the-bottom-up/ http://newartisans.com/2008/04/git-from-the-bottom-up/ 4. http://people.gnome.org/~newren/eg/ http://people.gnome.org/~newren/eg/
- etjossem 14y agoContext --- Master Git and a novice API developer stood together in a crowded office. "I am trying to merge two massive XML files," explained the API developer, "and I am getting many tedious conflicts. You must have a strategy for making the lines match up in a human-readable manner. What is my best option?" "Patience," said Master Git, turning away from the monitor. "But I have been manually resolving for hours!" protested the API developer. "My mergetool ought to be able to imply context and match lines properly!" Master Git sighed and left the room without a word. Hours later, he returned to find the office empty and silent. Only the API developer remained, his head bowed in defeat before the monitor. "git merge --strategy-option=patience," whispered Master Git. Upon hearing the same word in explicit context, the novice was enlightened.
- develop7 14y agoCreate a pull request to https://bitbucket.org/sjl/stevelosh https://bitbucket.org/sjl/stevelosh
- edem 14y agoI'm a relatively new git user. I'm rebasing a log when other developers commit unrelated changes. What is the problem with git rebase?
- qznc 14y agoI believe lots of people do not understand that you should treat remote branches differently than local branches. More precisely, you treat remote/global history differently than local history. Using rebase to clean you local history is ok. Maybe even recommended or mandatory depending on the project. Changing history, which is already in other people's repos, will lead confusion and should really be avoided.
- philsnow 14y agoI don't use a complicated .gitconfig (just user.name and user.email), so this is all new to me. Something that leaps out to me as horribly wrong is that aliasing a builtin doesn't cause the config file to be "invalid". Doing anything else is just doing spooky things that are explained only several hundred lines into the man page by a single sentence. Maybe better would be to choke on config lines that alias a builtin, and to print error messages before or after the output of each git command while the offending line(s) are present. Further, git config alias.pull "pull --ff-only" should definitely be an error. Instead, git gladly makes the (no-op) confusing edit to your config file.
- Aga 14y agoEven if this was meant as an critique to Git, I (some kind of a Git-evangelist) enjoyed it a lot. I even learned something new! The critique is quite well established. One needs to understand these quirks to be an enlightened Git user. However we make up with them, as the overall gain from Git's approach to version control is so big. Some things could be improved though, like introduce something like "git branch --current" to avoid the Hobgoblin...