Compare: `git branch xxx / git branch -a`, `git tag xxx / git tag -l`, `git show-ref --heads`
To: `hg branch xxx / hg branches`, `hg tag xxx / hg tags`, `hg heads`
There are also "duplicates" that I'm not sure why aren't folded into one command: `show-branch/branch`, `show xxx` which is `diff -c xxx` in many other systems, etc.
These are just simple cases, but there's loads of situations where you have to find out yet another command in git / yet another parameter to do what you want. Hg has better defined defaults and the whole list of commands looks like it was designed, while git looks like everyone just added what they needed... Auto-expanding commands in hg is also nice - I hate it when git tells me 'ci' or other short name is not a command (yeah, I know about aliases).
In some situations I also think that git does exactly what it's programmed to do... which isn't always the same as - what workflow makes sense in a specific case. For example `branch` creates a branch, but you still need to do `checkout` (or just `checkout -b ...`). Why? What's the common use case for creating a branch you're not going to work on? Which behaviour do you expect more often?
All in all, not the end of the world, but when you use the tool every day, it becomes annoying, especially if you see it can be done better.
git tag -a tagname
git push --tags
git checkout tagname
http://git.or.cz/course/svn.html
BTW, it's also worth noting that hg can have tag merge conflicts (http://mercurial.selenic.com/wiki/GitConcepts), which is just weird.
For anyone looking to learn more about git, I haven't found a better resource than this talk: (video) http://blip.tv/file/4094854 (slides) http://www.slideshare.net/chacon/getting-git
That said, I migrated from hg to git, and I love them both way more than svn.
`show xxx` which is `diff -c xxx`
There is a subtle difference. git-show is meant to show an object. A commit is an object, but so are other things. A more descriptive name would be 'git show-object.' git show <branch_name>:<filename>
This will show you the contents of <filename> on <branch_name>. It does not show you the diff of that file for the latest commit to <branch_name>; it spits out the state of that file to the $PAGER. This is something that 'git diff' does not do. Note that <filename> doesn't even have to exist on the current branch, and you don't even have to have a working tree (i.e. you can do this in a bare repo to inspect file contents without actually needing to checkout a working copy of all of the code).Git has had two main drawbacks in my mind. 1) Much of it is implemented as script commands, and I think it still requires you run an emulated shell in Windows to use it (by contrast, Mercurial is a pure python app, and is ultra-portable). 2) Coming from the Linux community, it seems a little heavy weight for small projects. Some command require what seem like extra steps on Git as compared to Hg. For example, Git requires that you do a "git add" before doing a "git commit". Mercurial assumes that you want to add all the changed files in your repo (or you can list the files needed in a commit).
For complex scenarios, Git's system does provide a bit more control in packaging up exactly the set of changes you want in each atomic revision.
Besides these minor historical differences, I think they both are excellent, and are really a matter of personal or team preference.
This is one of the features of git I most appreciated when I started using it (my first VCS was Mercurial).
I get distracted easily. While I'm rooting through the code base trying to do something, I'll notice something else to fix. And something else. And something else. By the time I've finished whatever I was trying to do in the first place, I've got 5 or 6 different things I've actually done.
In git, it's trivial to split these up - `git add` separate files, or `git add -p` when you only want to stage some of the changes in a file. This leads to cleaner commits.
I've heard people decry this, saying that you should be testing each individual state of your codebase. git being the powerful sonuvabitch it is, you can do that:
* `git stash --keep-index` will store away all of your modifications, other than the ones you're getting ready to commit. Run your tests, commit, `git stash pop`. * Checking out different revisions and running tests isn't a bad option, either, whether you use `git bisect` or do it manually. With the amazing power of `git rebase -i`[0], you can easily fix any little issues without disrupting other commits.
[0]: http://schacon.github.com/history.html
You will change their SHA1 sums, so they'll become different commits. This isn't a problem, though, if you haven't pushed them up to a shared repository.
git add just adds the file to the index and stages it for commit, this means you can group files logically depending on what has changed, you can even using git add -p have only certain parts of a files modifications be committed and the rest be staged for the next commit. This can be very powerful.
For example, if I did a full refactoring of a class, and fixed a quick bug rather than committing them both at the same time in the patch I can just keep the bug fix and then later commit the re-factored code even if it is in the same file.
Once you get used to having the ability to create arbitrary commits from a huge changeset, you'll find it aggravating when everyone else commits "3 bug fixes to core, swapping out a style sheet, and cleanup in database code" :)
aka push -f and yell at them.