"You decide to bring in some more code from the public repo. Here is a 6000 word essay on what rebase means."
"You try to look at an old version of the code. Suddenly you are in ‘detached HEAD’ state. The End."
I love git, but simple intros like this hide all the confusing complexity and awkward UI that quickly comes to the forefront when using git for everyday work.
Which has the effect of (a) making them fear Git, (b) making them feel like they'll never figure it out, (c) and convincing them that they're always on the verge of losing data. I've literally had students at the start of my course refer to Git as "that system that makes me lose files."
Once I teach people about Git's objects and data structures, things suddenly become much more obvious to these people. Git becomes less of a mystery.
I'm not saying that Git is easy for people to understand or use, because it isn't. It has a steep learning curve -- one which I think is worth the effort. But I think that it does a disservice to Git newbies to try to summarize all of Git's functionality in a short essay, and then proclaim, "See? There's not that much to learn here!"
To be very effective and safe using git, you really do need to understand a bit about its inner workings. I find that to be a big weakness of the tool, and it continues to surprise me that it's become as popular as it has. I personally like git a lot, and find it to be very powerful, but it took time and an interest in deep learning to get there.
I can certainly understand that most people might want a simple VCS that's easy to use and makes it difficult to screw up. Git is not that VCS, by any means.
I might start to teach courses online at some point, but I'm right now so busy with in-person classes in Israel and China (with a bit in Europe probably happening soon) that I haven't had a chance to consider it. But hmm, maybe...
Meanwhile, see my above reply with some suggested resources to learn about and understand Git. I hope that they'll help.
[1]: https://codewords.recurse.com/issues/two/git-from-the-inside...
[1]: https://www.dropbox.com/sh/quumaubjftxik1u/AAD15CT1UrNyOuYSx...
I personally think git is simple. That doesn't mean it's easy. The issues listed in the GP comment seem to me mostly social. I think the most common problems with git stem from a more general difficulty in working with a branching, asynchronously developed codebase.
About merges... I think rebase is ridiculously overused, and people should use merges more. Clearly a feature branch littered with spurious merges is bad, but often it seems that this is taken simply to mean that merges are bad, and I get the impression that people go to ridiculous lengths with rebase etc. just to preserve an illusion of linear history even in cases where merging would be better.
Of these, my particular favorite is Michael Schwern’s “Git for ages 4 and up." Watch this, and suddenly Git will make a ton of sense. Jessica Kerr's talk about Git is a close second; it's remarkable for telling us about how Git thinks about things without showing any code.
One of my favorite tools to use in my Git course is this site:
http://www.wei-wang.com/ExplainGitWithD3/
which graphically shows what happens when you commit vs. change branches vs. rebase. Super cool stuff.
If you go through the two of these, and if you understand them, I think that you'll have about 90% of what you need to then re-read a Git introduction, and have things make sense.
- The Git Book [1]
[0] http://tom.preston-werner.com/2009/05/19/the-git-parable.htm...
Alternatively, you could attend Recurse Center and sit through one of Mary's excellent git workshops. :)
Imagine you clone a repo. So your version is identical. You now add a couple more commits to master. Now, to make them identical again, all you have to do is upload the new commits, and then get his master branch to update to point to the latest one. Makes sense, right? That's a fast-forward.
Instead, what you do is merge your latest commit with the older commit two back, which creates a third commit with identical content to the previous one. That's silly, right? That's why fast-forward instead of merge.
> "You decide to bring in some more code from the public repo. Here is a 6000 word essay on what rebase means."
Rebase is when you take the content from a chain of commits, and make a completely new chain with that same content, just because it makes it look neater. You then change the branch from pointing at the head of the old chain to pointing at the head of the new. That's all it does. The old chain is still there until it's garbage collected a few weeks later (or you tag it to stop it disappearing).
> "You try to look at an old version of the code. Suddenly you are in ‘detached HEAD’ state. The End."
I'm not sure what the fear is here, so I'm not sure what to tell you. Create a test repository with a few commits and change the hashes below for real ones:
git checkout master # on master, whew
git checkout e34a53 # oh no, detached head
git checkout master # it's ok, back on master, whew
git checkout 343a34 # oh no, detached head
git checkout master # it's ok, back on master, whew
git checkout fe34ee # oh no, detached head
git checkout master # it's ok, back on master, whew
git checkout a567ed # oh no, detached head
git checkout master # it's ok, back on master, whew
Repeat until you're not panicking? :-) git checkout -B lastdeployed
to the end of your script would leave them happier!Then I gave up and went back to Mercurial. It does a much better job with subrepos, and I can actually use it without always consulting a hand-scrawled reference sheet for common tasks.
Mercurial's history rewriting is excellent. Do you know of `hg histedit`, `hg commit --amend`, `hg rebase`, `hg crecord --amend`?
If you're using Evolve, there's also `hg uncommit` and `hg amend`, amongst others:
https://www.youtube.com/watch?v=4OlDm3akbqg
(Demo begins around 9:10)
https://codewords.recurse.com/issues/two/git-from-the-inside...
ps: maybe it just fits my brain's inner working, I like to see every details before grasping the abstraction.
The thing about git is that the internals are sensible and cohesive, whereas the UI is a train wreck. This is the opposite of svn where the UI is simple, but the internals are a train wreck.
(And BTW my own simple subset is still simpler - no branches, for instance, as it helps people delay merges which IMO they tend to overdo even without branches; also helps people pull and think they "got the changes" without actually running the new stuff. Also, my own understanding of rebases, detached heads etc. etc. is minimal at best and I seriously dislike having to learn that sort of thing and having to keep it in mind.)
"You run 'git push --force'. You are likely to be eaten by a grue."
% git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
I assumed the working copy was up-to-date, as git states.... but alas, no. I had to do a "git pull" to get the latest changes. Why doesn't git tell you that your copy is out of date?To have git contact the remote again, you can do "git fetch origin" (or just "git fetch"). Then git will tell you your copy is out of date compared to origin/master, if there's been commits on origin since.
If you commit things, then your copy will be ahead of origin/master, so origin/master is what is out of date and you need to git push:
~/dotfiles % git status ✓✗ master:c024cb4 - dotfiles
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)It makes sense when you consider that there are other ways that origin/master could be updated. You could apply commits that someone emailed you (a common workflow in the Linux kernel that git was designed to support), or someone could push commits directly to you over SSH or the filesystem.
If you want `git status` to compare `.git/` with the state of a remote, you must first `git fetch` the state of a remote into your local `.git/`. And you may have multiple remotes, as well...
We're definitely staging a comeback. Mercurial's development is lively and interesting, and with the backing of the likes of Google, Facebook, Mozilla, and Atlassian, we definitely are seeing lots of good stuff in hg.
But 'origin' is just the name of the remote repository, not something hardwired into git, right? (Maybe this response is undercut by the fact that it is the default name.)
The reason git doesn't do this automatically is because, in its simple model, it doesn't waste time trying to connect to the remote 'origin' or any other remotes you may have configured every time you do 'git status', which is most often used to check what you've modified locally.
I can understand why this would be jarring coming from SVN, where you always want to be checking against the remote/server. Since git has a copy of all history locally, remotes are de-emphasized compared to centralized VCSs.
That's all there is to a branch. Do:
cat .git/refs/heads/master
in any git repo you have on your machine and see (compare it with 'git log')If you have a remote branch that points to the same commit, all that means is that there is a text file called ".git/refs/remotes/origin/master" which has the contents "a4300d840a4d01767cb2e768e51f7e88cb40e8cb". Again, that's all there is to a remote branch.
Well, ok, there's also an entry in your ".git/config" file that gives the URI for "origin" (or whatever you've named your remote server; origin is the default).
All these files are just text files. Have a look at them in your favourite text editor (or with less or whatever).
I realise this is likely an unpopular opinion, but I would challenge you to reply with justification rather than inevitably downvoting me into oblivion.
One of my software development mentors (a long time mechanical engineer who has done UNIX OS development for 20+ years) often has this as his email signature and I think it's rather apt in this context:
Civilization advances by extending the number of
important operations which we can perform without
thinking about them.
With that said, I'm not advocating complete ignorance of how a version control system "works", I just find the philosophy of "you must learn the internal data formats and workings of this system to use it effectively" more than a bit distasteful.I've never used it, but I've heard that Mercurial offers most of the power of Git, with much less of the pain, and an easier user interface. I'm willing to believe that this is true. I'll even believe (whether it's true or not) that Mercurial does provide a nice abstraction layer, one that allows you to ignore the underlying implementation.
The thing is, that doesn't matter at this point. Many people (including me) have gotten through the Git learning curve and now find it to be fantastically useful. I'm far more productive with Git than I was with SVN or CVS, and I'm not the only one to feel this way. As a result, you now have an ecosystem of tools, tutorials, books, etc. that all build on Git -- not to mention companies such as GitHub and GitLab that supply (relatively) easy-to-use tools and interfaces.
Also: A large part of Git's power stems from the fact that you're always thinking in terms of commits, and where those commits fit on your repository's graph. I'm not sure how you can abstract away from that, even if it's an interesting idea in theory.
A combination of critical mass (among open-source developers and a growing number of corporations), an ecosystem, and a powerful (if hard to understand) data model has made Git the standard nowadays. It's a crying shame that Git is so hard for so many people to get... but I've found that in my own work, the learning curve was more than worthwhile, and has made me more productive.
I've been using git for 5 years now, and I don't have a clear understanding of "its innards". I once read an overview of how it works under the hood and have a vague notion of what's going on.
What are the typical use case scenarios where you need to know implementation details to "avoid disaster"?
I can rebase/merge/push/pull/commit just fine while being ignorant of implementation.
Even thinking of Git as a security camera watching your shop (working tree), a VCR (record, forward, rewind history), a videotape copier (branching, pushing) and video editor (pulling, merging) wouldn't be too far off the mark, without the need for any reference to Git's inner workings.
Sure, a lot of Git talk mentions SHAs, trees, blobs, etc., but they could just as well have been brownies, blurfls, gizmos or whatever, as long as the practical context in which one needs these things is clear. Branches, tags and remotes are still the most useful top-level concepts, with no need for knowing their implementation details.
Only when one needs to do really low-level stuff like efficient import/export, history rewriting (ugh) etc. does one need to know a little more about how Git works. Many people have used Git for years without knowing anything about the plumbing beneath its porcelain.
Even then, I personally find Git's interface confusing and inconsistent -- there are various examples of that with how you request help (usage) for various commands.
The only way I can personally tolerate using Git at the moment is via SourceTree or the GitHub web interface.
That's just my personal opinion of course and isn't necessarily a factual reflection of Git itself.
I've used various source code control systems over the years: sccs, perforce, bitkeeper, cvs, svn, bzr, mercurial, and so on to various degrees if that means anything. The one I've finally settled on for personal use has been mercurial, which I've generally found fits my own workflows the best and generally has an interface that seems to work without me having to think about it too much.
This perspective has root in Fred Brook's observation "Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won’t usually need your flowcharts; they’ll be obvious."
I'm sure simple reverting is super easy once you know what you're doing, but you need to know what you're doing.
# revert a commit
git revert dd61ab32
I believe the problem here is that even though there are only a finite number of choices (less than a dozen in everyday life) representing what I want to accomplish, there are countless ways of getting there with commands. I just don't remember having these kinds of problems with svn, so I think the difficulty is not conceptual, but due to a poor mapping between the concepts and the interface.
I'm thinking something like Apple's Time Machine, where you click a commit and the repo shows up on the desktop as a mounted drive. We could use ordinary tools to edit the image and when it's unmounted it becomes a new commit (or something along those lines).
The official github client is trash. The last time I used it was a year ago, so it might have improved since then.
I do like the git-bash on Windows, though. For some reason I've avoided installing cygwin.... ever.
I'm reasonably comfortable with the git command-line tools, but for keeping the simple things simple I really do like an integrated all-in-one visual diff/VCS client program and SmartGit is the best one I've used for git.
SourceTree (mentioned by fsk) is kind of a trainwreck on Windows, in my experience (moving to SmartGit was the result of me getting fed up with SourceTree and looking for something not as frustrating). From what I understand the Mac version works better, though I haven't used it. While the UI is quite nice to start, the Windows version of SourceTree tends to soft-hang a lot (goes into non-responsive states it eventually recovers from, but will hang for like 30+ seconds at times) and it has a lot of weird issues with multi-monitor setups (it'll sometimes randomly jump to the other monitor during pane resizing and such).
I think what you're looking for here
> you click a commit and the repo shows up on the desktop as a mounted drive. We could use ordinary tools to edit the image and when it's unmounted it becomes a new commit
is basically `git checkout -b newbranch 80238ec` followed by `git commit -a`.
Other than that: This is a very short and concise introduction, especially the merging.
➜ ~ mkdir test1
➜ ~ cd test1
➜ test1 echo "hello" > hello.ttx
➜ test1 ls
hello.ttx
➜ test1 git init
Initialized empty Git repository in /home/david/test1/.git/
➜ test1 git:(master) ✗ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.ttx
nothing added to commit but untracked files present (use "git add" to track)
➜ test1 git:(master) ✗from `man git-clone`:
Cloning into an existing directory is only allowed if the directory is empty.[1] http://tom.preston-werner.com/2009/05/19/the-git-parable.htm...
"Most people try to teach Git by demonstrating a few dozen commands and then yelling “tadaaaaa.” I believe this method is flawed. Such a treatment may leave you with the ability to use Git to perform simple tasks, but the Git commands will still feel like magical incantations. Doing anything out of the ordinary will be terrifying."
Makes the 600 words achievement seem less impressive, if you put it in the context of existing git education.
These paragraphs do indeed cover those commands for git, although I can't see why this presentation is particularly useful, even for a beginner. It's just a condensed HOWTO that doesn't actually explain what it's doing.
Newcomers would be better advised to sacrifice the 30 minutes and read the first three chapters of the storied git book: http://git-scm.com/book/en/v2.
I strongly recommend that all new users read at least those first 3 chapters, but also the very useful chapters on using GitHub - a website that I have personally found extremely unintuitive to use.
For six hundred words, I think it does a good job.
git undo
and it just undoes whatever you just did. There seems to be a way to undo pretty much anything, but I usually end up googling and deciphering the likes of git reset HEAD hard -f --now origin/master --no-rebase %${%&`+'${`%&NO CARRIER")
Then when that goes wrong, you're in real trouble and left scratching your head at git's error message.Is this a joke I don't get?
My group project partner and I were having the toughest time with git last night. I thought we were all ready to walk out the door and then we ended up monkeying around with it for an hour and a half.
The atlassian visual guides really helped:
https://www.atlassian.com/git/tutorials/
They're great for people who know the names of all the git commands but who are still thrown off in really basic situations, ie 'Is it merge master? Merge origin master? Merge origin/master? Why does it say already-up-to-date?'
- git push when I needed to take work to Github
- git checkout when I needed to move between branches
- git merge when I needed to merge someone else work into master
- git cherry-pick I needed this to take commits from a non-fork to my project
- git bissect Debugging a bug introduced between releases
I also learned to use Github tools, SourceTree, the Command-Line and Bitbucket. If you want to learn git, just make a commit. Everything else will be mastered down the road.
Anyway, in case the author sees I thought they might want to know. And if it doesn't load for someone here, wait 30 seconds and it probably will.
I can see in the console your fonts are failing to load. Perhaps this is causing the issue?
"The conclusion I draw from this is that you can only really use Git if you understand how Git works. Merely memorizing which commands you should run at what times will work in the short run, but it’s only a matter of time before you get stuck or, worse, break something."
Add a couple of additional developers with 600 words of git understanding would result in chaos.
Here's the link: https://news.ycombinator.com/item?id=8932737 (see the comments for the correct link..)
I remember liking reading it.
Yes, as clear as mud. This is why I hate git. Why should code versioning be SO bloody complicated?!. Give me SVN or (shudder) CVS anyday.