This is less safe than the branching alternatives. Instead of "moving" the original commit, this copies the original commit to a new one and leaves the original one dangling and waiting to be garbage collected.
Also, if you have more than one commit before you noticed you were on the wrong branch, this only grabs the one commit.
Honestly, the proper command is not rm at all, because you can then have an "oh shit I forgot something" moment. I have learned (the hard way) to retain even an horribly broken repo, but shove it out of the way. Because disk is cheap, repeating work is expensive.
So that example should have been:
cd ..
mv fucking-git-repo-dir fucking-git-repo-dir.archived.$(date +%s)
git clone https://some.github.url/fucking-git-repo-dir.git
Actually the easiest thing is simply not to care about how your log looks.
If you don't then there are ry only two things you need to know how to do:
If you didn't push to origin do an ammend. If you did, revert soft and commit the previous code to revert it (you can also put a stash or patch to apply it back).
Which frankly is what the article does, basically.
> Actually the easiest thing is simply not to care about how your log looks.
Yes, that sounds as easy as anything that accepts the idea of "let's do this the shitty-but-quick way now, and pay the technical debt later". So yes, it is "easier" to work with in the beginning.
On the other hand, if I had to inherit your repository that was developed by "not caring about history", I would probably have to hunt you down and kill you. So there's that.
On the other hand, if I had to inherit your repository that was developed by "not caring about history", I would probably have to hunt you down and kill you. So there's that.
Yep. Some people just want to keep taking technical debt on (read: hack-it-'till-it-works), which makes them likely candidates for a good thrashing in some dark blind street in the middle of the night. And some don't even get it after that. Actually, now that you made me think about it, most people in this industry aren't really computer people material, that's the problem.
> Actually the easiest thing is simply not to care about how your log looks.
You need to expand on this because i don't quite understand what you mean, are you talking about "fix typo" commits or are we getting to the level of just committing away until things work and then not cleaning up the work later on? The linked article doesn't cover rebasing or squashing commits, which can be pretty powerful when used correctly.
Your commit log is the one thing that is immutably linked to your code changes. Your documentation isn't, the comments in your code aren't, you will forget why you made a change, anyone reviewing your logs needs to understand your intention, your bug tracker will probably change several times over the life of a project, and so on. So, make an effort to have a commit log that is clean and comprehensive and commits that don't break tests.
Develop on feature branches, merge with master only when the feature is done. Always merge with --no-ff. Then, when reviewing history, on the master branch you can use either "git log" or "git log --first-parent master". The first log is the complete log, with exploratory development, mistakes, backtracks and such. The second is the clean log people keep rewriting history to obtain.
This is pretty much the reason i don't understand people who don't want merge commits (the use case for rebase in the video is modifying commits in a feature branch BTW, not merging to master). You can bend git logs to your will with the various options so there's no problem in being as verbose as possible in commit messages and the concept of a "linear history" is a moot point because, no matter how messy your history actual is, there's a command line option to clear it up.
Be verbose in your commit messages and don't worry about merge commits, it will pay dividends later.
Having a messy and complex git log is not only about the visuals though. It can make it a lot harder to track down when/where/why bugs and problematic code was introduced. It makes both git bisect and git blame less useful.
Exactly. The canonical reference to how a git log should look is the Linux kernel, since git was written for it: https://github.com/torvalds/linux/commits/master Bisect and blame are amazing in that repo.
I managed to "rm -rf .git" at one point. Took me about a minute to realize and -surprisingly after <c-c>-ing i lost nothing (as far as i was aware). Git is freaking hard to break. Also always remember git-reflog, it safes lives.
I don't know if this post was intended as humour or a way to vent out some frustration but in my experience, this path of treating git as "spell X solves problem Y" will always break down.
Version control systems are an important part of the programmers toolkit and it's worth investing a little time to get the fundamentals right.
Sure git is not the friendliest of beasts but what it lacks in interface, it more than makes up in internal consistency and trying to learn it "inside out" is a better long term investment than having a list of ways to solve "git problems".
I think there's a bit of that in git in particular.
The irony is that if you think of git in terms of deltas, with branches just being tags to commits, and "git commit" actually being "git commit + move branch", then a lot of stuff is easier to reason about.
Like, if you get the notion of working tree, staging area, commits, and branches on a deep-ish level, things get easier. Things can still be hard, but there's a lot less "does running this cause everything to disappear???"
I think it would be possible to make this awesome page even more awesome with a little "annotated version" that gives the details of what you're actually doing.
> and "git commit" actually being "git commit + move branch"
Can you elaborate on that a little more? I liked where it was going -- because being able to explain how git works to someone coming from SVN has been an ongoing problem for me.
In git, branches are pointers to commits (branches are a specific kind of refs or references). When you commit, git creates a new commit object, links it to the last commit on
that branch, and then points that branch to the new commit.
This way, you get a chain of commits, each pointing to the previous commit, and and branch references pointing to the last commit of each branch.
Simplifying things a bit, git is what you did before you learned about using version control. That's right, it's just the old copy/paste the entire project folder for each revision and give it a name like "Project v1", "Project v2", etc. Branches and tags are then just symlinks to a specific folder.
In this world, when you commit, you're doing two things:
1. Creating a new top level folder, e.g. "Project v42".
2. Updating the branch symlink you are on to point to that new folder.
I'm actually not simplifying things that much here, the main git addition is that each folder (revision) also has a list of previous folders (revisions) and that the folders (revisions) are not named sequentially, they are named based on a hash of their contents.
Git has enough bells and whistles that a cheat sheet is fine, in my opinion. It's only a problem if you don't understand the commands (the same problem as blind copy-pasting code from the web)
it was really hard for me to understand vim until a website explained it as being a set of grammars you can learn.
i agree, if you really want to be more productive (and without having to go find some git expert on your team) knowing how each operation works and why its doing what its doing is really beneficial.
despite that, its sometimes frustrating due to inconsistencies in the git "grammar" that i sometimes don't understand, like why if you want to apply only one file from git stash you have to use `git checkout` rather than `git stash apply [<stash>] -- <file>`. it makes "sense" but is unintuitive when i'm thinking about using stashed commits.
The absolutely easiest way to learn vim is to just schedule a reminder every ... month? week? to run "vimtutor". Then do that for a few minutes until you get frustrated or want to do something else. It's shocking how fast you'll learn.
I agree that it's worth it learning git properly, but sometimes you're thrown into the deep end and don't have the time to get up to speed the "right way". I think git is complicated enough to warrant some simplified descriptions for the most-required tasks.
At this point I think we need to define what it means to "learn git properly". The assumption in this discussion is that it is more than learn a few concrete commands for specific tasks in a few minutes. You say 3 hours is sufficient, but is it?
For example, something as simple as "Changing the Last Commit" (as in "git commit --amend") is found in chapter 7.6 in the git book which is given as main documentation on git-scm.org. The first 6 chapter mainly deal with introducing the model, architecture and high level workflows. Even if you skip the chapter on github, that's still 5 chapters on mostly theory to read before you get to some often-used tool commands. I would argue that is more than 3 hours for most people if you don't just skim it but try to also understand it.
Apart from that, to answer the question: indeed, often I don't have 3 hours for something to be considered "nice to know" as opposed to "absolutely necessary". And if the manual is a "fsckin'" one, I'm unlikely to read it at all.
I think the biggest problem people have with git is that you can't and shouldn't want to change shared history, and yet git provides some tools that suggest that maybe you can.
It's better to accept history as it is, and fix the problem with reverts, cherry-picking and new commits. History won't be as pretty or clean, but it will reflect what actually happened, which is what history is, after all.
The biggest trick to understanding git is to learn to think in commits rather than file content. If one branch has a commit and the other branch doesn't, merging them will mean that the commit is there. If one branch has the commit while the other branch has the commit and a revert for that commit, merging will mean it will be reverted.
Same goes with pushing. If you reset locally to before a commit that you already shared, that commit returns on your next pull. If you revert it, it will stay reverted.
The most dangerous thing git can do, is rebasing. Rebase changes history. This is fine if it hasn't been shared yet (you commited a new change and try to push, but remote changes need to be pulled first, so rebasing is fine). Rebasing is not fine if the commit has already been shared, through a different branch or a different remote repository, for example. In that case, you need a merge.
As pretty as rebase can make your history, you should really only use it when you understand what it does. If you don't, stick with merge.
`git rebase -i` by default rebases only back to the first commit you haven't shared (at least that's how I interpret the actual behaviour). This is a great default - it's the simplest way to change history and at the same time powerful without being too dangerous.
Ah, interesting. I'd noticed this behaviour but hadn't conciously thought about it.
The docs say:
All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area. This is the same set of commits that would be shown by git log <upstream>..HEAD
Well yeah, sometimes this power is needed. For example, I might need to do a rebase over published history to remove a patch that was found to be a copyright infringement.
I think the ability to edit history is one of the great advantages of Git. I encourage people to use it rather than ignore it.
Cleaner history makes life much easier for those who will try to understand what you did weeks or months or even years later (including your future self).
Of course, you shouldn't (with rare exceptions) edit history you have already shared with others; but, I never found that concept, or the way git implements it, particularly hard to understand. (I will admit some of git's commands are hard to remember - I am always forgetting the difference between "git reset --hard" and "git reset --soft".)
> If one branch has a commit and the other branch doesn't, merging them will mean that the commit is there. If one branch has the commit while the other branch has the commit and a revert for that commit, merging will mean it will be reverted.
See, I fundamentally disagree that this is what I wanted. When I merge my thing with change x into head I expect to see my changes actually go in. Not to see commits retroactively added to head. The merge was the action, not some weird rewriting of historical order of events.
> The biggest trick to understanding git is to learn to think in commits rather than file content.
Ok, I'm starting to see what you meant. (I didn't understand this until the second part and my being confused as heck)
> I think the biggest problem people have with git is that you can't and shouldn't want to change shared history, and yet git provides some tools that suggest that maybe you can.
Funny, I think the biggest problem is people who refuse to understand the caveats of rewriting shared history and spread FUD about it.
Knowing Git "inside out" is great, but you can't expect to know/remember every command for every situation from day one or even day one thousand. A list of ways to solve Git problems serves as a refresher and even a tool for gaining more insight into how it works as a whole.
"Not the friendliest of beasts" is putting it mildly.
Git is basically Linus in a nutshell: abrasive, unforgiving, and behaving like an absolute asshole to any non-expert struggling user.
Sure, engineers should probably get to know its quirks and learn to work around them because it's now ubiquitous in the field, but let's not pretend that there's something virtuous about it. This is a piece of truly terrible software with an even worse UX that just happened to win the PR battle against its superior foes, because...Idunno, Linux, I guess?
I'm struggling to see which VCS you deem superior, I'm assuming you are not referring to SVN, Mercurial maybe?
The learning curve to git is not great but as far as I know nobody has publicly released an option that's improved enough over git to motivate the cost of switching technology. If it's not working for you the only advice I can give is either learn it until it is actually working for you rather than being in the way or try to find a better workflow.
SVN is much easier to use for the standard corporate workflow of a group of people making commits to a project which mostly advances monotonically with continuous integration.
Edit: also in a Windows environment, svn copes slightly better than git. First project we tried it on had the worst possible environment, a mix of Windows and Linux systems. Line ending nightmares everywhere.
It also took a while to work out how to kill (with fast-forward) the spurious "merge commit" you get every time someone does a pull. You don't have that with svn, you just do the merging locally when you update and it doesn't generate a commit.
I concur. I would assume that git is the right tool for Linus's workflow, but whatever that is, it isn't mine. SVN does all I need and it has a friendly API and helpful documentation. In other words, the exact opposite of git.
I've been using Subversion since 10 years or so and I've changed completely to Git, so I've got experience with it.
For me Git was really a much needed upgrade to subversion. Working with branches (testing and production, we even have some repositories with multiple testing and production branches) are working like they are supposed to do.
Changing commits (oops - I forgot to add one file) before pushing them to the repository for the other users is another big advantage.
Working on multiple features in parallel - I couldn't do that with Subversion.
We've nearly completely eliminated the "handcrafted" local copies with multiple half finished features since changing to Git.
And if you want to use Git as a Subversion alternative you can use it in this mode too - altough you are missing out on some good new features.
I don't want to change back to Subversion.
The only disadvantage is that SourceTree (the GUI tool we are using) is a pretty lame duck in Windows. But the command line is excellent.
I really like modifying commits (as long as they are not pushed) - but I know that this is quite a controversial topic.
For one of our biggest projects branches in SVN didn't work at all.
We have multiple production, test and development branches and merge branches (features) from one branch to the other (development -> testing -> production). Sometimes we cherry pick a single commit to another branch.
In those days SVN wasn't so flexibel with branches as we wanted to (or we didn't understand it enough), so our workflow was much more rigid.
I'm prepared to give you a lot of examples (which other people might value differently). From the unfortunate consequences of the 'branches are files (and therefore tags are easily mutable by default and surprisingly hard to pin down)' to usual "I just committed, why does 'svn log' not show that?", to git bisect, to git clean and the stubbornness with which svn refuses to even consider implementing that.
that sounds like process-issues... not SVN issues.
tags should not be committed to... end-of-story.
as for 'svn-log not showing commits'... I've never heard of that one in the last decade of using it... I'm genuinely interested in how that came about.
I used SVN for 7 or 8 years and then Git for the past 3, with about a year of overlap (on different repos).
To me, Git is vastly superior. I tend to use it in quite an "SVN-like" fashion - there's a single main trunk branch that we all share - but in terms of what I can do locally it blows SVN out of the water.
The difference is that Git makes things that are hard or impossible in SVN trivial. So for e.g. I create local branches all the time; I commit a bunch of small changes locally as I experiment with a fix, and then `merge --squash` to leave a clean history for others; merging fixes across different branches is easy and just works.
Yep, Mercurial's the one. It's a shame that it lost the war, they actually seemed to care about providing a good experience to their users. There are, of course, a few technical differences between it and git, but I personally never felt like they were troublesome enough to make up for the vast difference in usability.
I think Mercurial hasn't lost it yet. I speak as a creator of Mercurial Source Code management system (RhodeCode)
We see that a lot of companies(our clients/users) adopting Mercurial, you just don't hear about it. Often those are companies with employees that don't tweet or post to HN ;)
RhodeCode is used also in around 60 universities, and we learned that in a lot of them they teach Mercurial as well as Git.
For a large company it's actually much cheaper to adapt Mercurial as they new DVCS because of learning curve.
I hope companies like Facebook and Mozilla will make soon Mercurial very very fast. There's constant work on it coming from those companies to improve it.
I don't think hg is going anywhere, if CVS is still alive and kicking in 2016, and especially since Facebook's using it. However, IMO hg lost when even python switched to git.
I don't know any of the other distributed version control systems. The only other version control system I have much (too much) experience with is Subversion and it can't hold a candle against Git.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you. Otherwise you have a really great tool with lots of power.
>subversion is still king in the corporate-engineering companies and it tends to work well in those types of setups.
For some values of "work". We're using SVN at my new job, with a single trunk branch. Not having the ability to commit locally, and mess around with local branches is a pain in the ass. I found a solution though. I cloned SVN repo using git-svn and now I can make local commits like a pro, and use my beloved magit (Emacs git interface).
Yes, git-svn is probably the reason why the mutiny didn't happen yet in some departments. You can identify their users by having several SVN commits in as many seconds.
(I used git in an cvs-to-svn migration, and stayed since.)
for me the biggest advantage is working in my own repository and then pushing the changes upstream. I can develop features independent of other features. If there is a bug I can fix it, merge it into the productive branch and carry on working on other features.
I know that many people don't like it, but I can fix up commits in my local repository and push the change upstream in one.
With SVN I wasn't able to do this, so it was a big pain if you had to fix a bug if you were in the middle of a big feature, or if you had an experimental feature you wanted to clean up and release a month later.
I don't know any of the other distributed version control systems.
In an ideal world -- one where network effects of GitHub hadn't crushed all competition -- I'd get to choose Mercurial as my daily version-control system. It has similarities to git, in that both are largely user interfaces to a DAG, but its guiding philosophy and approach to the interface it exposes are far better in my opinion.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you.
You probably don't want to make that assertion; we now have close to half a century of evidence that no human currently living can use C safely, and I don't think you'd want that to carry over to git. And it's not a matter of "careless" or not -- extremely intelligent, extremely-well-trained, extremely-careful people still write unsafe C.
>we now have close to half a century of evidence that no human currently living can use C safely
How many operating systems are written in C ?
How many of the more mainstream operating systems are written in other languages ?
You're right that C is the wrong tool for a lot of applications. But if you need total control and speed and power it still works for many projects.
I've heard a lot of people who seem to know their stuff say that Mercurial is superior to Git in almost every way, especially when it comes to integrating with other tooling (i.e. Mercurial seems to have an API whereas automating Git boils down to spawning shell commands). This also seems to be why Facebook switched from Git to Mercurial: they needed to be able to check out individual folders from a branch and Git simply didn't provide any way to do that without first checking out the entire branch.
Be that as it may, it's a common misconception that the more popular tool is always the better tool. There are a lot of factors to a tool's success and the technical ones are generally far less important than most people think.
People have already mentioned it, but since I made the original comment, I'll pile on and say that Mercurial was (well, still is, but it's out of fashion now) awesome. It matches Git on most axes and blows it out of the water when it comes to usability and "don't shoot yourself in the foot"-ishness.
Brushing aside some relatively minor differences, Mercurial is very similar to Git, except that it was designed by people that don't have an all-consuming disdain for all of humankind.
> He knows a lot about his domain, sure, but he's no god and there are a lot of areas he knows diddley-squat about.... user interface design for one!
And Einstein knew nothing about biology.
I'm sure he knows "diddley-squat" about most areas, but as long as he knows a lot about his domain then he's an expert.
And he is good at user interface design, and git is a good example of that; it's just not aimed at beginners. It was designed by and for expert users, and the interface fits that very well.
admittedly "expert" UIs are different from "noob" UIs, but the number of "git magic spell" followers out there mean that it isn't a good UI for the majority of people who use git.
Well, if you treat git as Torvalds intended it in the beginning (framework for
building VCS-es) and accordingly limit the discussion to git's plumbing
command set, you get a sensibly good UI+architecture that is targeted at
programmers that write VCS-es.
Git being operable with a pry bar and repairable with a hammer is a good proof
that in this context it's a good design.
Chalk that up to the power of fashion. Otherwise, people would use an SCM that doesn't destroy their work in the blink of an eye and actually has an API that deserves the name.
I think besides a PR battle (there's PR people for RCS'es??) I think Git won out because "the server was free". Competitors at the time needed a big (if there were large numbers of committers) server that someone had to pay for. By that I mean the hardware to host the server -- Git needs either none, or a very lightweight machine for a server.
The Git DAG and its content-addressable file system are an elegant solution to the problem of distributed version control. The implementation is clean and dead-simple, yet immensely powerful. This is the basis of good engineering.
> an even worse UX
Git was designed to expose its underlying implementation and not to isolate the user from it. Unlike other systems, its subcommands give the user the ability to manipulate the underlying data structure directly.
That doesn't mean it has a bad UX. Just that it has the UX of a power tool.
I also think that Git played a big role in the growth and popularity of command-line tools over the past decade. And that its interface inspired the subcommand pattern that is now commonplace in docker, vagrant, and others.
>I don't know if this post was intended as humour or a way to vent out some frustration but in my experience, this path of treating git as "spell X solves problem Y" will always break dow
I disagree. "spell X solves problem Y" is an excellent way to both get started with fixing your Y fast AND for learning a system deeper.
I think we better learn by example (such as that) and in practical use over time, as opposed to getting some abstract knowledge of the whole system first, or (god forbid) reading the manual, which noone does.
I disagree. Using Git (or any terminal interaction for that matter) is much like speaking a language. As a metaphor: you might be able to order two beers in German (zwei Bier bitte), but the moment the waitress asks you what brand you want it comes down to guessing.
Some coworkers (across all experience levels) use Git this way. It's frustrating how slowly they learn and conversely, how inefficiently they work.
>Using Git (or any terminal interaction for that matter) is much like speaking a language
Which again, we learn best by absorbing bits and pieces piecemeal over time -- that's how toddlers learn their native language, by immersion. Not by getting some "understanding of fundamentals" course first.
I think the reason you're disagreeing is that you're not looking at this from a beginner's point of view.
Generally there are (roughly) three approaches depending on where you are in your journey from beginner to expert:
As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
Once you've moved beyond being a beginner, you understand how the different steps are connected, so you already know the intermediate steps and just need to be told the task at hand: do an X (e.g. "move these commits onto the other branch").
An expert fully understands all the inner workings and just needs to be told the big picture: this is what I have, that is what I want, make it happen.
If you try to instruct experts like beginners, they will be frustrated because it seems so tedious and you're not giving them the information they want: what you're trying to do. If you try to instruct beginners like experts, they will be horribly confused because they don't know how to make any of it happen without you laying out each individual step they need to follow.
A case can be made that a beginner should learn each individual operation by heart before moving on to the next one (like kata in martial arts) but this style of learning assumes you're willing to spend a lifetime perfecting a single art. It's unlikely git will stick around that long and for most of its users git is just a tiny (though important) aspect of their work.
"A lifetime" is massively exaggerated. I would argue that I know the majority of intricacies of every git command, and I've spent much less than a lifetime on this (about 2 years in reality, alongside other things, of course).
> As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
That's one way to do it, but it's not preferable. I would rather sit the beginner down for at least an hour and go through the basic concepts with them.
I've taught Git to a few people (mostly fellow students or colleagues) and I found that they have a much easier time when they are introduced early on to the basic concepts of Git (the commit graph, and branches/tags as pointers into the graph), they have a much easier time grasping relevant tasks like merge and rebase.
For specific questions (mostly in these "I screw up" moments), a whiteboard is also really helpful to explain them how the two or three magic commands that I tell them are actually fixing things up.
> this path of treating git as "spell X solves problem Y" will always break down
I agree completely! Anytime you give a list of 'run this command', I think you've actually written a CLI tool in the wrong language (English instead of a programming language).
At work, we want to increase dev's confidence with git in the next few months. We're making sure to separate out 'Technical' knowledge (what do steps do I perform to recover a deleted branch) from 'Conceptual' knowledge (why would it be a good/bad idea to delete a branch, how branches are intended to be used, understanding what git thinks a branch is, etc.). The former go into git aliases or CLI swiss army knife tool, the latter into training videos and workshops.
Any points on how to continue from there? Been in a few "I give up" conditions during rebases that I completely stopped trusting git it any way.
The thing is, some repositories on github require you to commit only after proper rebasing. But I can never in my life remember how and need to google it...
> Been in a few "I give up" conditions during rebases that I completely stopped trusting git it any way.
Been there too, with the same result.
> Any points on how to continue from there?
Honestly? Not always from the command-line, unfortunately. Basically, I just don't know the right commands to type on the command-line for everything I do with git, and it's not necessarily easy to find them either. I use the TortoiseGit GUI, and over there, it's a LOT more easy to see what is going on and to abort or continue rebases/merges as necessary, or to do fancier stuff. But the thing is, because I understand git and I know what should logically happen at every step, I can cherry-pick commits, revert them, abort/continue merges, rebase commits, or do whatever else the heck I want without getting into trouble anymore... even though I don't know how to do many of them on the command line.
Of course, it took a lot of suffering to get here. Starting with the GUI would of course be the wrong approach. But once you've understood what's going on, then I would recommend you entirely ditch the command line and switch to something like TortoiseGit (I hope you're either on Windows or your platform has something as good as that). The GUI actually shows you what your options are at every step, so you don't have to know all the valid commands at every possible state. You just need to know what effect you need to cause.
> Been in a few "I give up" conditions during rebases that I completely stopped trusting git it any way.
People use rebase in a far too casual way. Rebasing is a pretty advanced use case, one that is unnecessary for normal git usage. You sentence sounds like: I stopped trusting Ford because the car stopped working when I reprogrammed the ECU.
In short: If you are not entirely comfortable with git's inner workings, do not use rebase. Do not complain if you shoot yourself the foot with rebase.
I'm still at uni (at a highly ranked but actually crap university where we don't learn git properly) and this year was my 'year in industry' as we call it in the UK, and my first proper experience with git, aside from `git init` at the end of my project and pushing it to a repo.
I've become so much more confident with git. Seriously, with one caveat (i.e., you haven't pushed your changes to a branch which other developers are working on), it is almost impossible to break irrevocably. Even if you do accidentally break master/develop/whatever, it only causes a bit of hassle and grumbling.
Highly recommend that everyone take a bit of time to learn about "undoing" git commands, whether that's through soft resets, hard resets to origin, or the reflog.
Reflog is also useful for figuring out how someone else broke something and explaining what they did wrong, since you can see what branch they were on at what commit and what commands they ran.
I think git's main problem is the somewhat arcane language it uses, and lack of understanding of what's actually happening behind those words like "rebase", "commit", "patch", "reset" etc.
This tells me you still don't get the point about using a revision control system: the whole point is NOT that you can hack the revision control system's database every which way, but that you can never, as in ever, break something in a repository, because you can always revert the previous commit and do a new commit of that revert. Keeping it simple since January 1st, 1970.
It's called the "unceremonious revert", popularized by Jeff Bonwick, the father of ZFS and former Solaris gatekeeper, in the "Quality death spiral":
Bonwick was granted authority to "rip it out if itʼs broken" — an early BDFL model, and a template for later generations of engineering leadership.
...and do youserlf a favor, try out Bitkeeper (it's open source!) before you get completely absorbed into git. You might never be able to get out of that tar pit afterwards, or it might be decades before you realize it. Who will compensate you for all that lost time, and how would you be compensated?
And? You will have some kind of 'blessed' repo anyway. In git you disable non-fast-forward pushes there (aka prevent commits from ever being removed) there, and implemented your 'point'.
I would not expect a university to teach git. Maybe the theory of version control systems, their history, or a comparison of different version control systems.
I agree. Class time is much too valuable to be lost on such minutiae. However, I'd expect a good university to:
a) Explain the value of version control and actively promote its usage
b) Drop some hints on which good version control systems are out there, one of which is git, then let students pick, learn and run with their own choice
It'd take all of half an hour, with great benefits for students.
I agree because of the large variety of version control tools. Git is great IMHO, but not every company uses it or can easily switch to it. Teach some theory or the basics of a few different systems and their pros and cons, but I don't think diving too deeply into only one is a good idea in a university environment.
Perhaps not specifically git, but ANY version control would have been good.
We were told to version control a group project, but all we were given was an SVN repo and told "if anything goes wrong, email this address".
Personally I would expect tuition through the use of a tool, that tool doesn't have to be git, it just so happens to be the tool I've had the most exposure to.
I had to take a class, Principles of Software Engineering, that was a sort of hands-on class. We went over different methodoligies like waterfall vs agile, scrum, the use of kanban boards, design documents, and the use of version control. The version control lession was basically an assignment saying "do the Udacity git course". Alongside this, we had a group project where we had to, well, develop something.
Not quite in the spirit of this article, but "I just want this /one/ file without the rest of the changes from branch foo" is something I use all the time
I can't believe no one has responded yet with "use a GUI". After gaining a basic understanding of how branches and merges work, and I do mean basic, I've never been able to screw up a local repo with a GUI client enough that I haven't been able to recover with the same GUI tools.
I understand that people need to know how to use their tools, but for git most people can get away with the very basic usage that GUIs provide. If you've made some unrecoverable mistake with an important set of changes, you can always review the history in the same GUI and reimplement the important changes in a new branch.
I like to use a GUI for things like viewing staged/unstaged files, their riffs, and picking which files to stage for a commit, but for every other situation, the command line is just so much faster and easier to understand what's actually happening.
Agreed, a GUI have most of the functionality and a clear visual representation of the state of your repo.
When it's not enough the terminal is once click away
I have to disagree, I've seen people paint themselves into really hard to get out of corners by using GUI tools and not understanding the underlying tool. git GUIs are leaky abstractions that sometimes even change the meaning of core git concepts. I always recommend people start by using git at the command line until the have a solid understanding of how the tool works before switching to a GUI.
Yes. I teach git professionally and when I do, my approach is to stick to describing the nuts and bolts. Once people use it from the command line and get things done, they (usually) understand what's going on pretty well but are annoyed by the nitty gritties of the command line. Then they're ready to move on to a tool of their choice but can always map the actions there back to the data structures inside git so they've never lost. Also, they can always drop back down to the command line for any low level surgery that the client doesn't provide.
I completely agree with this one. I encourage our developers to always use the cli, even if they are not familiar with the core concepts of git. I see myself as a mediocre git user, but there are some situations, however, where I prefer to use a GUI for more complex operations, like staging/un-staging specific lines or create/apply patches.
Oh, i did, yes i did. I wish there was a refund on wasted life.
Process Explorer- are those crashed git instances still around?
Yes.
Can i kill them now with admin priv?
Nope.
Gui still frozen?
Yes.
Can i get Git-bash?
Yes.
Can i do something usefull with it?
No, session is still open in the gui.
No, don't get all riled up. I know what you will tpye beneath this.
"..Put all the dummys in a reeducation camp, with electric fences around it.." ".. cementing superiority is what is all about, fuck the specialization that got humanity this far.." didn't sound like a opinion that can change the last time.
Its true -- and actually the well designed gui that accurately depicts the graphical state of your local repository makes it far easier to learn the concepts behind git than does the command line. Distributed vc is conceptually nuanced, but not overly complicated -- the complexity of git really is in the interface wherein you are asked to map command line syntax into abstract operations that manipulate a state that you actually can't easily see from the command line. The value of having a graphical depiction of the state that's changing as you invoke operations should not be underestimated.
I love this tool -- it's honestly one of the best graphical tools I've ever used -- rock solid reliable -- intuitive, not leaky in the abstractions it represents -- and not limited to only "simple" operations. And with the graphical reflog history rollback view -- it's always really easy to back up however far you want if you mess up which gives great confidence as you explore the ui's features. Ive taken designers from "never used git" to confidently pushing, pulling, rebasing, and resolving conflicts in less than a day (and most of it after the first 10 minutes without outside help).
Just ran `brew cask install gitup`, cd'd into my repo and ran `gitup`. Took about 60 seconds and so far it's quite impressive.
Clicking on a commit and pressing space brings up a view showing a github-style diff, a list of all changed files, and the complete commit message. Nice.
I had to do a site visit with a customer recently and spent some time pair programming on their codebase -- on a Windows machine and they used an awful git client -- really reminded me how much I appreciate using gitup!
I don't know how it compares to GitUp, but SmartGit works on Linux, Windows, and macOS. I use it on all three platforms and recommend it highly. See my other comment in the subthread for more thoughts about it.
True, SmartGit is not open source or free-as-in-speech. It is free-as-in-beer if you use it for open source or noncommercial purposes. I use it for commercial projects and didn't blink at their price - it's paid for itself many times over.
I can't think of a single time I've actually ever cared to look at anything other than a linear history or a single file's blame. I do have a 'hist' alias set up (http://blog.wittchen.biz.pl/basics-of-git/#gist16617665), but it's not something I ever actually use.
Good for you. I'm probably not as smart and more likely to get confused without having the history laid out in the form of a clean, coloured graph. At any rate, it allows me to free whatever brain power I have for other purposes
I agree, and often use a `log --bunch -of --options` alias to view this - but slightly prettier rendering isn't going to make me switch window and back again.
I actually used to think similarly before I found git up -- although to me
it wasn't about switching window context away from the terminal but rather switching away from the text editor. I imagined that the ideal place for featureful visualization/interaction with the repo would be in the text editor/ide. In reality though -- i really like having the separate window -- it's always there, does one thing and does it well, and it's easy to switch to when I want to take a look at the state of my repo/upstream branches/any dirtiness in my checkout (what exactly have I done recently?). I regularly use three editors when working on different platforms -- Xcode, android studio, atom -- sometimes it's convenient to use in ide repo-driven features (blame, sometimes historical diffs for a single file), however very often I'm actually more interested in quickly seeing diffs for files other than the one(s) I'm currently editing -- so switching to a separate app context that's all about showing repo info tends to be the fastest way to see the relevant info I want side by side without changing away from the editing context I want. More often than not navigating to most relevant diffs within the ide would actually involve more expensive context switching -- for me I'm discovering that it's always somewhat high risk to switch editor contexts -- editing text is just such a powerful interface that it tends to easily lead down rabbit holes that take me further from the most relevant info for my current task context. Once I have the most useful buffers in the right windows, with maybe some reasonable things in the editor navigation stack -- changing the editor views at that point comes with a pretty high risk of straying off task -- or operating for awhile with the non optimal set of editor windows in front of my face -- which at some point I'll realize is dumb/wastes energy and fix -- but energy was already spent in the meanwhile ...
Honestly I'm not aware of any common repo tasks that I could more efficiently complete via the command line vs gitup. There are good keyboard shortcuts for everything in gitup so most everything I do doesn't even involve the mouse.
Also -- I'm the kind of person who's always got a set of terminal windows open and definitely uses them often (almost never use Finder, hate taking my hands off the keyboard to reach for the trackpad). At this point -- I never reach for the git cli over gitup (except when cloning a new repo).
I'm using mac at the moment, and the awful window management (and inability to properly change it - all wm apps just handle resizing and moving within existing spaces and margins) just makes me more motivated to do everything in full-screen tmux, to simulate a decent wm - as long as everything is CLI-based!
(I tried Arch on it for a while, but ended up deciding the firmware difficulties - in particular the battery draining quickly and CPU running hotter - weren't worth it; I traded i3 for full-screened tmux.)
Preach! I absolutely love gitup; all of these slice-and-dice operations that are brainteasers in command-line git are just intuitively obvious in gitup. Absolutely one of my favorite pieces of software, ever.
git is basically a brilliant repo model combined with an insane cli. gitup is the brilliant ui that the repo model deserves.
bonus awesome thing about gitup: it monitors the filesystem and updates its state in realtime, so it it's seemless to mix your workflow between cli and gui.
I stopped using a GUI (SmartGit) when I encountered an error which was talking about stashes and something like {0}. I had no idea what the error was. Now I know how these tools work but I think that you can only use them effectively if you learn how they work and how the underlying system works. If you fail to do so you end up with a leaky abstraction which will at some point (and believe me it will) present you with an error message you don't understand and you end up with a problem you can't recover (yet). GUIs are fine but only if you know the ins and outs of the underlying system.
I'm with you. I've been using SmartGit for years and would never go back to the weak sauce of the command line, except for a few odd things that SmartGit doesn't cover (like bisect).
Every one of the tasks in the article is a simple, straightforward operation in SmartGit. Take "I accidentally committed something to master that should have been on a brand new branch!" or "I accidentally committed to the wrong branch!" for example.
Instead of an obscure series of four to six commands, you simply go to SmartGit's log view and drag the branch markers to where you want them. Easy and intuitive.
I know GUI tools are a hard sell for a lot of programmers. I honestly don't understand why. I think it may be the fear that you'd be giving up power, but SmartGit isn't a dumbed-down GUI. It gives you a more powerful set of tools, and much more visibility into the state of your repo.
You're not even giving anything up. You can still use the command line whenever you want, and SmartGit shows you the commands it used to accomplish each task.
Of course you still need to understand the underlying Git concepts to use any GUI effectively, but a tool like SmartGit lets you see those concepts.
I am surprised that somebody claim that has messed up a git repo. Since I started using git, I haven't ever messed up with my code.
I always use git on the command line. Regarding GUI tools I like to avoid them, for me is too much noise. People get lost most of the time because they don't know what the tool is doing. After all is just one more layer on top of git core tool per se (aka, what you have in command line).
I've never really screwed it up that badly using the command line either. I don't know what these people are trying to do that they constantly mess up their repository so bad they can't fix it. Perhaps being too obsessed with having a perfect commit history.
I've seen repos completely borked because the gui kept a merging and pushing in the background. This was after spending a lot of time removing binaries from a repo and not being able to figure out how the same binaries kept ending up back on origin.
I agree, and while I have not tried the other apps mentioned here, I do rely extensively on Atlassian SourceTree client for Mac and find it very useful.
I've worked with a guy who only uses GUI tools for Git and he's supposed to be a senior dev and doesn't know how to resolve a simple merge conflict and regularly wipes out other peoples' work with whatever he's doing with the tool.
Is the documentation really that bad? Would it benefit from a technical writer going over it? Is the project open for discussion on changes to the documentation?
Git is like Perl. And not in any of the good ways.
Perl 5 -- I don't know enough about 6 to know whether this is still the case -- involved a couple of design decisions which worked well for one subset of people and did whatever the complete polar opposite of "works" is for a different subset of people.
One of those design decisions is the famous "there's more than one way to do it". Ask five Perl programmers to solve a simple problem in the language and you'll get fourteen solutions, and no way of knowing which, if any, is to be preferred in real-world use. Git similarly tends to have multiple ways of achieving a given goal, and endless words have been devoted to documenting them; nobody has yet settled which of them is or should be generally recommended, or if there even can be such things as generally-recommended ways to use git.
Perl also involves an incredible amount of memorization. The large collection of "magic" variables which can be read or set to determine language and local-scope behavior are daunting and can't be mastered through any process other than rote memorization. And the differing behavior of basic operations depending on context produces a combinatorial explosion of possibilities which, again, are not amenable to any technique short of rote memorization. The same is true in git: though there are underlying abstractions, the interface provided to them is inconsistent, varies depending on sometimes-invisible contextual factors, and ends up requiring rote memorization of commands and options and how they behave in any given situation.
Unfortunately, no amount of documentation or review by technical writers can fix this. A bad API can't be made good through better documentation, it can only be made good through being replaced with a better API.
I am a long-time Perl user and also a long-time Git user.
Git is worse than Perl. Perl is just opinionated: despite what you are saying about it is true, you can write working programs and have fun at all levels of Perl mastery. There's a lot to memorize, but you can start coding immediately and do something useful. Also, Perl community is incredibly friendly and helpful.
Not so with Git. If you start without thorough understanding how Git internals work, you will get burned really soon. And more often than not, the only response you'll get is the arrogant RTFM or the link to Pro Git book.
Good points. Also, git (not Perl though) was designed by a genius for himself (and a few other geniuses). All of whom don't know how much of a genius they are / don't comprehend how comparatively dumb the rest of us are. So, the git ui assumes you either "wrote git" or "have read the source and are smart enough to understand all it's implications".
# create a new branch from the current state of master
git checkout -b some-new-branch-name
# remove the commit from the master branch
git checkout master
Or just `git branch some-new-branch-name`...
cd ..
sudo rmdir nsfw-git-repo-dir
That will only remove it if it's empty? Which it never will be, because there's at least `.git/*`...
Yep, git sucks but it's all the rage now. Mercurial is 100x nicer to use and logical, but since it's written in Python it's slow as molasses, especially with large binary files.
Next on the list: Larry McVoy's Bitkeeper promises to be everything git and Mercurial aren't. (git is "inspired" (read: copycat) by Bitkeeper).
It's funny how Sun Microsystems influenced the industry in so many ways, isn't it?
If you're concerned about not knowing how to do certain things with git, and understanding at a deeper level how git works, I highly recommend reading Scott Chacon's "Pro Git" book:
That book is great, and so is the built-in gittutorial(7). If you really want to get down and dirty with Git, I'd also strongly recommend going one step further and reading gitcore-tutorial(7). It shows you the man behind the memorized commands curtain.
351 comments
[ 4.7 ms ] story [ 269 ms ] threadAlso, if you have more than one commit before you noticed you were on the wrong branch, this only grabs the one commit.
http://stackoverflow.com/questions/28759887/git-gc-no-space-...
So that example should have been:
If you don't then there are ry only two things you need to know how to do:
If you didn't push to origin do an ammend. If you did, revert soft and commit the previous code to revert it (you can also put a stash or patch to apply it back).
Which frankly is what the article does, basically.
Yes, that sounds as easy as anything that accepts the idea of "let's do this the shitty-but-quick way now, and pay the technical debt later". So yes, it is "easier" to work with in the beginning.
On the other hand, if I had to inherit your repository that was developed by "not caring about history", I would probably have to hunt you down and kill you. So there's that.
Yep. Some people just want to keep taking technical debt on (read: hack-it-'till-it-works), which makes them likely candidates for a good thrashing in some dark blind street in the middle of the night. And some don't even get it after that. Actually, now that you made me think about it, most people in this industry aren't really computer people material, that's the problem.
You need to expand on this because i don't quite understand what you mean, are you talking about "fix typo" commits or are we getting to the level of just committing away until things work and then not cleaning up the work later on? The linked article doesn't cover rebasing or squashing commits, which can be pretty powerful when used correctly.
Your commit log is the one thing that is immutably linked to your code changes. Your documentation isn't, the comments in your code aren't, you will forget why you made a change, anyone reviewing your logs needs to understand your intention, your bug tracker will probably change several times over the life of a project, and so on. So, make an effort to have a commit log that is clean and comprehensive and commits that don't break tests.
I go into this in more detail in a talk i gave last week: https://www.youtube.com/watch?v=9OHAq8dCoS4
You get your cake and you can eat it too.
Be verbose in your commit messages and don't worry about merge commits, it will pay dividends later.
Other ways to do it (that don't require to retype the commit message): - rebase onto the correct branch:
- cherry-pick > Oh shit, I tried to run a diff but nothing happened?!You probably want to know `git diff HEAD` too.
Edit: formatting.
Version control systems are an important part of the programmers toolkit and it's worth investing a little time to get the fundamentals right.
Sure git is not the friendliest of beasts but what it lacks in interface, it more than makes up in internal consistency and trying to learn it "inside out" is a better long term investment than having a list of ways to solve "git problems".
The irony is that if you think of git in terms of deltas, with branches just being tags to commits, and "git commit" actually being "git commit + move branch", then a lot of stuff is easier to reason about.
Like, if you get the notion of working tree, staging area, commits, and branches on a deep-ish level, things get easier. Things can still be hard, but there's a lot less "does running this cause everything to disappear???"
I think it would be possible to make this awesome page even more awesome with a little "annotated version" that gives the details of what you're actually doing.
Can you elaborate on that a little more? I liked where it was going -- because being able to explain how git works to someone coming from SVN has been an ongoing problem for me.
This way, you get a chain of commits, each pointing to the previous commit, and and branch references pointing to the last commit of each branch.
In this world, when you commit, you're doing two things: 1. Creating a new top level folder, e.g. "Project v42". 2. Updating the branch symlink you are on to point to that new folder.
I'm actually not simplifying things that much here, the main git addition is that each folder (revision) also has a list of previous folders (revisions) and that the folders (revisions) are not named sequentially, they are named based on a hash of their contents.
i agree, if you really want to be more productive (and without having to go find some git expert on your team) knowing how each operation works and why its doing what its doing is really beneficial.
despite that, its sometimes frustrating due to inconsistencies in the git "grammar" that i sometimes don't understand, like why if you want to apply only one file from git stash you have to use `git checkout` rather than `git stash apply [<stash>] -- <file>`. it makes "sense" but is unintuitive when i'm thinking about using stashed commits.
Thank you!
So you don't have three hours to read the fsckin' manual that describes how git repository is organized? O_o
For example, something as simple as "Changing the Last Commit" (as in "git commit --amend") is found in chapter 7.6 in the git book which is given as main documentation on git-scm.org. The first 6 chapter mainly deal with introducing the model, architecture and high level workflows. Even if you skip the chapter on github, that's still 5 chapters on mostly theory to read before you get to some often-used tool commands. I would argue that is more than 3 hours for most people if you don't just skim it but try to also understand it.
Apart from that, to answer the question: indeed, often I don't have 3 hours for something to be considered "nice to know" as opposed to "absolutely necessary". And if the manual is a "fsckin'" one, I'm unlikely to read it at all.
It's better to accept history as it is, and fix the problem with reverts, cherry-picking and new commits. History won't be as pretty or clean, but it will reflect what actually happened, which is what history is, after all.
The biggest trick to understanding git is to learn to think in commits rather than file content. If one branch has a commit and the other branch doesn't, merging them will mean that the commit is there. If one branch has the commit while the other branch has the commit and a revert for that commit, merging will mean it will be reverted.
Same goes with pushing. If you reset locally to before a commit that you already shared, that commit returns on your next pull. If you revert it, it will stay reverted.
The most dangerous thing git can do, is rebasing. Rebase changes history. This is fine if it hasn't been shared yet (you commited a new change and try to push, but remote changes need to be pulled first, so rebasing is fine). Rebasing is not fine if the commit has already been shared, through a different branch or a different remote repository, for example. In that case, you need a merge.
As pretty as rebase can make your history, you should really only use it when you understand what it does. If you don't, stick with merge.
Recorded history is not necessarily what actually happened though, often (or always, according to some) it's an interpretation.
"History is written by the victors" - Walter Benjamin?
The docs say:
All changes made by commits in the current branch but that are not in <upstream> are saved to a temporary area. This is the same set of commits that would be shown by git log <upstream>..HEAD
Cleaner history makes life much easier for those who will try to understand what you did weeks or months or even years later (including your future self).
Of course, you shouldn't (with rare exceptions) edit history you have already shared with others; but, I never found that concept, or the way git implements it, particularly hard to understand. (I will admit some of git's commands are hard to remember - I am always forgetting the difference between "git reset --hard" and "git reset --soft".)
See, I fundamentally disagree that this is what I wanted. When I merge my thing with change x into head I expect to see my changes actually go in. Not to see commits retroactively added to head. The merge was the action, not some weird rewriting of historical order of events.
> The biggest trick to understanding git is to learn to think in commits rather than file content.
Ok, I'm starting to see what you meant. (I didn't understand this until the second part and my being confused as heck)
Funny, I think the biggest problem is people who refuse to understand the caveats of rewriting shared history and spread FUD about it.
Git is basically Linus in a nutshell: abrasive, unforgiving, and behaving like an absolute asshole to any non-expert struggling user.
Sure, engineers should probably get to know its quirks and learn to work around them because it's now ubiquitous in the field, but let's not pretend that there's something virtuous about it. This is a piece of truly terrible software with an even worse UX that just happened to win the PR battle against its superior foes, because...Idunno, Linux, I guess?
The learning curve to git is not great but as far as I know nobody has publicly released an option that's improved enough over git to motivate the cost of switching technology. If it's not working for you the only advice I can give is either learn it until it is actually working for you rather than being in the way or try to find a better workflow.
Edit: also in a Windows environment, svn copes slightly better than git. First project we tried it on had the worst possible environment, a mix of Windows and Linux systems. Line ending nightmares everywhere.
It also took a while to work out how to kill (with fast-forward) the spurious "merge commit" you get every time someone does a pull. You don't have that with svn, you just do the merging locally when you update and it doesn't generate a commit.
For me Git was really a much needed upgrade to subversion. Working with branches (testing and production, we even have some repositories with multiple testing and production branches) are working like they are supposed to do. Changing commits (oops - I forgot to add one file) before pushing them to the repository for the other users is another big advantage. Working on multiple features in parallel - I couldn't do that with Subversion.
We've nearly completely eliminated the "handcrafted" local copies with multiple half finished features since changing to Git.
And if you want to use Git as a Subversion alternative you can use it in this mode too - altough you are missing out on some good new features.
I don't want to change back to Subversion.
The only disadvantage is that SourceTree (the GUI tool we are using) is a pretty lame duck in Windows. But the command line is excellent.
branches are branches in svn or git... your process may not have been correct, but lets not blame the tools here..
modifying commits is a big no-no for me, so thats not a drawback at all, the fact that its not possible in svn is a win for svn.
For one of our biggest projects branches in SVN didn't work at all.
We have multiple production, test and development branches and merge branches (features) from one branch to the other (development -> testing -> production). Sometimes we cherry pick a single commit to another branch.
In those days SVN wasn't so flexibel with branches as we wanted to (or we didn't understand it enough), so our workflow was much more rigid.
The SVN UI is just horrid in other dimensions, mainly the "you can't do that at all" one.
(getting down-voted for it, but someone has to say it)
tags should not be committed to... end-of-story.
as for 'svn-log not showing commits'... I've never heard of that one in the last decade of using it... I'm genuinely interested in how that came about.
I used SVN for 7 or 8 years and then Git for the past 3, with about a year of overlap (on different repos).
To me, Git is vastly superior. I tend to use it in quite an "SVN-like" fashion - there's a single main trunk branch that we all share - but in terms of what I can do locally it blows SVN out of the water.
The difference is that Git makes things that are hard or impossible in SVN trivial. So for e.g. I create local branches all the time; I commit a bunch of small changes locally as I experiment with a fix, and then `merge --squash` to leave a clean history for others; merging fixes across different branches is easy and just works.
Most people just spout the same sheep-like line "git>svn" without being able to justify it!
We see that a lot of companies(our clients/users) adopting Mercurial, you just don't hear about it. Often those are companies with employees that don't tweet or post to HN ;)
RhodeCode is used also in around 60 universities, and we learned that in a lot of them they teach Mercurial as well as Git.
For a large company it's actually much cheaper to adapt Mercurial as they new DVCS because of learning curve.
I hope companies like Facebook and Mozilla will make soon Mercurial very very fast. There's constant work on it coming from those companies to improve it.
I don't know any of the other distributed version control systems. The only other version control system I have much (too much) experience with is Subversion and it can't hold a candle against Git.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you. Otherwise you have a really great tool with lots of power.
Not saying I disagree... but subversion is still king in the corporate-engineering companies and it tends to work well in those types of setups.
Just beware of having unjustified-opinions. SVN may not be trendy... but neither will git in a few years time.
BTW: Mercurial still beats them all.
For some values of "work". We're using SVN at my new job, with a single trunk branch. Not having the ability to commit locally, and mess around with local branches is a pain in the ass. I found a solution though. I cloned SVN repo using git-svn and now I can make local commits like a pro, and use my beloved magit (Emacs git interface).
(I used git in an cvs-to-svn migration, and stayed since.)
I know that many people don't like it, but I can fix up commits in my local repository and push the change upstream in one.
With SVN I wasn't able to do this, so it was a big pain if you had to fix a bug if you were in the middle of a big feature, or if you had an experimental feature you wanted to clean up and release a month later.
In an ideal world -- one where network effects of GitHub hadn't crushed all competition -- I'd get to choose Mercurial as my daily version-control system. It has similarities to git, in that both are largely user interfaces to a DAG, but its guiding philosophy and approach to the interface it exposes are far better in my opinion.
In my opinion Git is the C language of version control systems. If you are careless it's not the tool for you.
You probably don't want to make that assertion; we now have close to half a century of evidence that no human currently living can use C safely, and I don't think you'd want that to carry over to git. And it's not a matter of "careless" or not -- extremely intelligent, extremely-well-trained, extremely-careful people still write unsafe C.
You're right that C is the wrong tool for a lot of applications. But if you need total control and speed and power it still works for many projects.
Be that as it may, it's a common misconception that the more popular tool is always the better tool. There are a lot of factors to a tool's success and the technical ones are generally far less important than most people think.
Brushing aside some relatively minor differences, Mercurial is very similar to Git, except that it was designed by people that don't have an all-consuming disdain for all of humankind.
You forgot "brilliant".
He knows a lot about his domain, sure, but he's no god and there are a lot of areas he knows diddley-squat about.... user interface design for one!
And Einstein knew nothing about biology.
I'm sure he knows "diddley-squat" about most areas, but as long as he knows a lot about his domain then he's an expert.
And he is good at user interface design, and git is a good example of that; it's just not aimed at beginners. It was designed by and for expert users, and the interface fits that very well.
admittedly "expert" UIs are different from "noob" UIs, but the number of "git magic spell" followers out there mean that it isn't a good UI for the majority of people who use git.
Git being operable with a pry bar and repairable with a hammer is a good proof that in this context it's a good design.
Chalk that up to the power of fashion. Otherwise, people would use an SCM that doesn't destroy their work in the blink of an eye and actually has an API that deserves the name.
And (c) lose the entire subtree the repo is in.
I think besides a PR battle (there's PR people for RCS'es??) I think Git won out because "the server was free". Competitors at the time needed a big (if there were large numbers of committers) server that someone had to pay for. By that I mean the hardware to host the server -- Git needs either none, or a very lightweight machine for a server.
The Git DAG and its content-addressable file system are an elegant solution to the problem of distributed version control. The implementation is clean and dead-simple, yet immensely powerful. This is the basis of good engineering.
> an even worse UX
Git was designed to expose its underlying implementation and not to isolate the user from it. Unlike other systems, its subcommands give the user the ability to manipulate the underlying data structure directly.
That doesn't mean it has a bad UX. Just that it has the UX of a power tool.
I also think that Git played a big role in the growth and popularity of command-line tools over the past decade. And that its interface inspired the subcommand pattern that is now commonplace in docker, vagrant, and others.
I disagree. "spell X solves problem Y" is an excellent way to both get started with fixing your Y fast AND for learning a system deeper.
I think we better learn by example (such as that) and in practical use over time, as opposed to getting some abstract knowledge of the whole system first, or (god forbid) reading the manual, which noone does.
Some coworkers (across all experience levels) use Git this way. It's frustrating how slowly they learn and conversely, how inefficiently they work.
Which again, we learn best by absorbing bits and pieces piecemeal over time -- that's how toddlers learn their native language, by immersion. Not by getting some "understanding of fundamentals" course first.
Generally there are (roughly) three approaches depending on where you are in your journey from beginner to expert:
As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
Once you've moved beyond being a beginner, you understand how the different steps are connected, so you already know the intermediate steps and just need to be told the task at hand: do an X (e.g. "move these commits onto the other branch").
An expert fully understands all the inner workings and just needs to be told the big picture: this is what I have, that is what I want, make it happen.
If you try to instruct experts like beginners, they will be frustrated because it seems so tedious and you're not giving them the information they want: what you're trying to do. If you try to instruct beginners like experts, they will be horribly confused because they don't know how to make any of it happen without you laying out each individual step they need to follow.
A case can be made that a beginner should learn each individual operation by heart before moving on to the next one (like kata in martial arts) but this style of learning assumes you're willing to spend a lifetime perfecting a single art. It's unlikely git will stick around that long and for most of its users git is just a tiny (though important) aspect of their work.
> As a beginner, you need specific, detailed, step-by-step instructions: First run X, then run Y, finally run Z, if something goes wrong along the way, follow these other steps, if that doesn't work, ask someone for help.
That's one way to do it, but it's not preferable. I would rather sit the beginner down for at least an hour and go through the basic concepts with them.
I've taught Git to a few people (mostly fellow students or colleagues) and I found that they have a much easier time when they are introduced early on to the basic concepts of Git (the commit graph, and branches/tags as pointers into the graph), they have a much easier time grasping relevant tasks like merge and rebase.
For specific questions (mostly in these "I screw up" moments), a whiteboard is also really helpful to explain them how the two or three magic commands that I tell them are actually fixing things up.
I agree completely! Anytime you give a list of 'run this command', I think you've actually written a CLI tool in the wrong language (English instead of a programming language).
At work, we want to increase dev's confidence with git in the next few months. We're making sure to separate out 'Technical' knowledge (what do steps do I perform to recover a deleted branch) from 'Conceptual' knowledge (why would it be a good/bad idea to delete a branch, how branches are intended to be used, understanding what git thinks a branch is, etc.). The former go into git aliases or CLI swiss army knife tool, the latter into training videos and workshops.
https://git-scm.com/docs/git-reflog
The thing is, some repositories on github require you to commit only after proper rebasing. But I can never in my life remember how and need to google it...
Been there too, with the same result.
> Any points on how to continue from there?
Honestly? Not always from the command-line, unfortunately. Basically, I just don't know the right commands to type on the command-line for everything I do with git, and it's not necessarily easy to find them either. I use the TortoiseGit GUI, and over there, it's a LOT more easy to see what is going on and to abort or continue rebases/merges as necessary, or to do fancier stuff. But the thing is, because I understand git and I know what should logically happen at every step, I can cherry-pick commits, revert them, abort/continue merges, rebase commits, or do whatever else the heck I want without getting into trouble anymore... even though I don't know how to do many of them on the command line.
Of course, it took a lot of suffering to get here. Starting with the GUI would of course be the wrong approach. But once you've understood what's going on, then I would recommend you entirely ditch the command line and switch to something like TortoiseGit (I hope you're either on Windows or your platform has something as good as that). The GUI actually shows you what your options are at every step, so you don't have to know all the valid commands at every possible state. You just need to know what effect you need to cause.
Running it gives you a log of all the things `HEAD` has ever pointed at, meaning you can find what you had before a rebase and check that out.
And you're usually good to go.People use rebase in a far too casual way. Rebasing is a pretty advanced use case, one that is unnecessary for normal git usage. You sentence sounds like: I stopped trusting Ford because the car stopped working when I reprogrammed the ECU.
In short: If you are not entirely comfortable with git's inner workings, do not use rebase. Do not complain if you shoot yourself the foot with rebase.
I'm still at uni (at a highly ranked but actually crap university where we don't learn git properly) and this year was my 'year in industry' as we call it in the UK, and my first proper experience with git, aside from `git init` at the end of my project and pushing it to a repo.
I've become so much more confident with git. Seriously, with one caveat (i.e., you haven't pushed your changes to a branch which other developers are working on), it is almost impossible to break irrevocably. Even if you do accidentally break master/develop/whatever, it only causes a bit of hassle and grumbling.
Highly recommend that everyone take a bit of time to learn about "undoing" git commands, whether that's through soft resets, hard resets to origin, or the reflog.
Reflog is also useful for figuring out how someone else broke something and explaining what they did wrong, since you can see what branch they were on at what commit and what commands they ran.
I think git's main problem is the somewhat arcane language it uses, and lack of understanding of what's actually happening behind those words like "rebase", "commit", "patch", "reset" etc.
This tells me you still don't get the point about using a revision control system: the whole point is NOT that you can hack the revision control system's database every which way, but that you can never, as in ever, break something in a repository, because you can always revert the previous commit and do a new commit of that revert. Keeping it simple since January 1st, 1970.
It's called the "unceremonious revert", popularized by Jeff Bonwick, the father of ZFS and former Solaris gatekeeper, in the "Quality death spiral":
Bonwick was granted authority to "rip it out if itʼs broken" — an early BDFL model, and a template for later generations of engineering leadership.
https://web.archive.org/web/20091028095830/http://hub.openso...
https://wiki.smartos.org/display/DOC/Community+History
SEE ALSO
http://dtrace.org/blogs/bmc/2015/09/03/software-immaculate-f...
...and do youserlf a favor, try out Bitkeeper (it's open source!) before you get completely absorbed into git. You might never be able to get out of that tar pit afterwards, or it might be decades before you realize it. Who will compensate you for all that lost time, and how would you be compensated?
@mathieuh was only referring to not being able to break the something in the repo, He didn't mention hacking the git or the git data structure.
Also, @mathieuh is a uni student, so comments like
> This tells me you still don't get the point about using a revision control system
Can come across a little unnice.
See also 'svn obliterate'.
But not how to use the tool.
a) Explain the value of version control and actively promote its usage
b) Drop some hints on which good version control systems are out there, one of which is git, then let students pick, learn and run with their own choice
It'd take all of half an hour, with great benefits for students.
We were told to version control a group project, but all we were given was an SVN repo and told "if anything goes wrong, email this address".
Personally I would expect tuition through the use of a tool, that tool doesn't have to be git, it just so happens to be the tool I've had the most exposure to.
Like cherry picking, force pushing, merge --no-commit, rebasing... almost any operation can end up going wrong.
Just pay attention.
I understand that people need to know how to use their tools, but for git most people can get away with the very basic usage that GUIs provide. If you've made some unrecoverable mistake with an important set of changes, you can always review the history in the same GUI and reimplement the important changes in a new branch.
I use magit myself for most things.
I mainly use the GUI for day-to-day stuff. Only in rare cases will I need to mess with the command line.
No, don't get all riled up. I know what you will tpye beneath this. "..Put all the dummys in a reeducation camp, with electric fences around it.." ".. cementing superiority is what is all about, fuck the specialization that got humanity this far.." didn't sound like a opinion that can change the last time.
http://gitup.co
I love this tool -- it's honestly one of the best graphical tools I've ever used -- rock solid reliable -- intuitive, not leaky in the abstractions it represents -- and not limited to only "simple" operations. And with the graphical reflog history rollback view -- it's always really easy to back up however far you want if you mess up which gives great confidence as you explore the ui's features. Ive taken designers from "never used git" to confidently pushing, pulling, rebasing, and resolving conflicts in less than a day (and most of it after the first 10 minutes without outside help).
Clicking on a commit and pressing space brings up a view showing a github-style diff, a list of all changed files, and the complete commit message. Nice.
Thanks for the tip!
I had to do a site visit with a customer recently and spent some time pair programming on their codebase -- on a Windows machine and they used an awful git client -- really reminded me how much I appreciate using gitup!
Seems like there's a glut of these apps of late—not that I'm complaining! :-)
I used to use a GUI for git, but now I just find them cumbersome; by their nature requiring me to switch window for less.
Honestly I'm not aware of any common repo tasks that I could more efficiently complete via the command line vs gitup. There are good keyboard shortcuts for everything in gitup so most everything I do doesn't even involve the mouse.
Also -- I'm the kind of person who's always got a set of terminal windows open and definitely uses them often (almost never use Finder, hate taking my hands off the keyboard to reach for the trackpad). At this point -- I never reach for the git cli over gitup (except when cloning a new repo).
I'm using mac at the moment, and the awful window management (and inability to properly change it - all wm apps just handle resizing and moving within existing spaces and margins) just makes me more motivated to do everything in full-screen tmux, to simulate a decent wm - as long as everything is CLI-based!
(I tried Arch on it for a while, but ended up deciding the firmware difficulties - in particular the battery draining quickly and CPU running hotter - weren't worth it; I traded i3 for full-screened tmux.)
git is basically a brilliant repo model combined with an insane cli. gitup is the brilliant ui that the repo model deserves.
bonus awesome thing about gitup: it monitors the filesystem and updates its state in realtime, so it it's seemless to mix your workflow between cli and gui.
Every one of the tasks in the article is a simple, straightforward operation in SmartGit. Take "I accidentally committed something to master that should have been on a brand new branch!" or "I accidentally committed to the wrong branch!" for example.
Instead of an obscure series of four to six commands, you simply go to SmartGit's log view and drag the branch markers to where you want them. Easy and intuitive.
I know GUI tools are a hard sell for a lot of programmers. I honestly don't understand why. I think it may be the fear that you'd be giving up power, but SmartGit isn't a dumbed-down GUI. It gives you a more powerful set of tools, and much more visibility into the state of your repo.
You're not even giving anything up. You can still use the command line whenever you want, and SmartGit shows you the commands it used to accomplish each task.
Of course you still need to understand the underlying Git concepts to use any GUI effectively, but a tool like SmartGit lets you see those concepts.
https://gitextensions.github.io/
Disclaimer: I'm now a GitLab authorized training partner and reseller. The community edition is free. :)
I always use git on the command line. Regarding GUI tools I like to avoid them, for me is too much noise. People get lost most of the time because they don't know what the tool is doing. After all is just one more layer on top of git core tool per se (aka, what you have in command line).
If you're used to the commands from the keyboard, where you're likely already typing from your editor...can't imagine going back to the GUI.
No thanks.
Perl 5 -- I don't know enough about 6 to know whether this is still the case -- involved a couple of design decisions which worked well for one subset of people and did whatever the complete polar opposite of "works" is for a different subset of people.
One of those design decisions is the famous "there's more than one way to do it". Ask five Perl programmers to solve a simple problem in the language and you'll get fourteen solutions, and no way of knowing which, if any, is to be preferred in real-world use. Git similarly tends to have multiple ways of achieving a given goal, and endless words have been devoted to documenting them; nobody has yet settled which of them is or should be generally recommended, or if there even can be such things as generally-recommended ways to use git.
Perl also involves an incredible amount of memorization. The large collection of "magic" variables which can be read or set to determine language and local-scope behavior are daunting and can't be mastered through any process other than rote memorization. And the differing behavior of basic operations depending on context produces a combinatorial explosion of possibilities which, again, are not amenable to any technique short of rote memorization. The same is true in git: though there are underlying abstractions, the interface provided to them is inconsistent, varies depending on sometimes-invisible contextual factors, and ends up requiring rote memorization of commands and options and how they behave in any given situation.
Unfortunately, no amount of documentation or review by technical writers can fix this. A bad API can't be made good through better documentation, it can only be made good through being replaced with a better API.
Git is worse than Perl. Perl is just opinionated: despite what you are saying about it is true, you can write working programs and have fun at all levels of Perl mastery. There's a lot to memorize, but you can start coding immediately and do something useful. Also, Perl community is incredibly friendly and helpful.
Not so with Git. If you start without thorough understanding how Git internals work, you will get burned really soon. And more often than not, the only response you'll get is the arrogant RTFM or the link to Pro Git book.
Still, amusing :)
Next on the list: Larry McVoy's Bitkeeper promises to be everything git and Mercurial aren't. (git is "inspired" (read: copycat) by Bitkeeper).
It's funny how Sun Microsystems influenced the industry in so many ways, isn't it?
alias gitshit="open http://ohshitgit.com/"
https://progit.org/
But does anyone know why this project has two homes?
https://git-scm.com/book/en/v2
Also, I think everyone should go through Neo's Git Immersion at some point early in their experience with git. It is the best crash course by far.
alias gitshit="open http://ohshitgit.com/"