Hacker News new | past | comments | ask | show | jobs | submit login
Git pretty (justinhileman.info)
314 points by todd8 on Sept 6, 2014 | hide | past | favorite | 63 comments

This is excellent: opinionated and correct.

Guess what happens if you try to git revert a merge? Yeah. Don’t do that.

You can, but you really need to understand what happens when you do so, so that you're not confused by future merges from the same branch. Straight from the horse's mouth:


Reverting a merge is totally OK if you kept your history clean and rebased the branch you're merging into to get updates instead of merging it into your branch.

Like if you created a new branch from master and you have been merging master into your branch to get updates in master, once you merge your branch into master you cannot revert this merge because the act of merging master into your branch changed which branch owned commits.

If you rebased master into your branch instead everything will be fine. If you merge your branch into master, reverting that merge will simply undo the merge as you expected.

I've read that doc and other warnings about reverting a merge. But I've found that if you revert the revert, then you avoid the problems they mention. I guess the worry is that you still have to remember to do that, or you'll have commits that silently never merge. But if you do remember, then reverting the revert makes things okay. But I'm no expert. Can anyone else confirm this for me?

Yes, the correct way to do it is to revert the revert. js2's link above outlines how and why in detail.

While I agree this guide is great, I think opinionated and correct are mutually exclusive.

"...opinionated and correct are mutually exclusive."


Very true, but whenever that is the case, there are typically some who decide their way is the "right" way for various reasons.

"Split off a logical chunk from your mess, stage it" should really be another box with "git add -p".

Being able to pick and choose (and even edit) individual chunks to be staged is enormously useful. Quite possibly my favourite feature of git.

Once upon a time I used darcs, where the interactive staging / interactive committing feels even nicer. Git's "git add -i" stuff has always seemed crufty to me.

For instance, in git add -i, the command to stage changes is called "update". The command to unstage is called "revert". Further, does _anybody_ use interactive adding when not intending to stage individual hunks from some file ? Yet there are all these other commands in there to stage/unstage whole files, which are more easily and uniformly done from the command line tools (well, when you accept that staging is called "add"ding on the command line and unstaging is called "reset"ting).

I agree with the git add -p , but I feel that at point, it often should be followed by a stash then a rebuild and/or some testing. Next, commit and unstash to continue.

Yep yep. `git add -p`, `git stash -p`, etc. That's exactly why that bit of the chart isn't very specific. There's a whole workflow right there, in that one little cycle. One of these days I'll get around to writing that one up :)

git isolate! I've been trying to make something like this :( Unfortunately my git-fu is failing me.

Mine too.

If you ever want that functionality on a non-git VCS, I co-wrote a tool that does just that (it predates git, actually) called commit-patch[1]. It integrates into Emacs nicely and also has 'commit-partial' for a nice command-line interface.

[1] http://porkrind.org/commit-patch/

> Quite possibly my favourite feature of git.

Mine, too. Fortunately, mercurial has that feature, too. (Though you might need a plugin.)

git add -p has absolutely changed my work flow and commit histories for the better.

I find that git add -p is a crutch and everytime I need to use it I scold myself for not committing more often.

That does sound useful, I have a bad habit of letting things get messy.

Lots and lots of rebase -i.

That's in the tl;dr

Mercurial Changeset Evolution is going to solve the "It's safest to let it stay ugly then" and "Send them a note, let 'em know you're changing history" problems. No more force pushes or lost data! The new version of history applies on top of the old version. Immutable data structures, flexible workflow.

As a one person web design/development studio, it's charts like this and threads like this that keep me off git. I've played with it, used it on a project but the fact that I am always reading about the messes people get in with git...I really don't have time to deal with versioning messes.

I'd counter that these messes aren't caused by git; rather they are messes that without git you wouldn't even bother cleaning up.

However, git lets you fix the mess in such a way that you'll have a clean commit history. This is really helpful if you're trying to keep your codebase clean so that `git bisect` will always work nicely, and if you just want to keep your codebase history really grokkable.

Oh, I'm not blaming git. I take full blame but still have a hard time rationalizing the headache.

I think any version control software needs to address the simple fact that humans will rush through writing and committing code in a way that they may later regret. Dealing with an ugly git log is less trouble than not having versioning software at all.

Yes, you are correct. I'm just not facing the inevitable apparently.

I do both enterprise and one person dev studio work and use Git for both.

When I do personal development or small side projects I could care less about my history being clean. Nothing is ever so large or complex that it needs to be fixed in such a meticulous manner. It may feel that way, until you start working on larger software. The stress of a $1,000-$20,000 job is laughable compared to the scale of enterprise failure.

In enterprise, it's often the case that applications are built by teams of people in constant flux. They may need to be patched or rolled back at a moment's notice, and every hour the bug stays live is an hour of enormous financial burden to the client and intense stress on my employer. In this case, having a trustworthy VCS with a clean history in invaluable.

magit mode in emacs has bailed me out numerous times from git messes. If you're an emacs and git user but not using magit, you're seriously missing out.

Dunno, I've been very happy with egg. But then, due to a large part of my career being maintenance, I've fallen into a lot of self-discipline patterns that tend to keep me out of messes.

egg looks pretty similar to magit in terms of functionality. I haven't tried it, but I would guess either one is fine.

That is a really fun poster to have!

I hope of course that people realize you should not rely on this as an educational tool but merely as a quick reference. Please, don't use any of these commands without knowing what they do!

"Do you hate them?" was hilarious.

If you really mess things up, there is Reflog

If you like this, check out gitjk[0], it's saved my codebase a handful of times.

[0] https://github.com/mapmeld/gitjk

What does "I don't think it means what you think it means" refer to?

Reverting a merge commit is the big danger zone.

Let's say you are working on a feature branch and you accidentally commit it to the upstream branch before you're ready. Intuitively, you might then revert the merge changeset, continue working on your feature branch for a while, and then when you're done, merge it back upstream.

That would be wrong.

What will actually happen is that when you do the second merge, only the changes you made after the reverted merge will be applied to the upstream branch. All the work that was "reverted" in the initial mistaken merge will be missing, even after the second merge! This can be very confusing, since there's no indication to the developer where it went. It's just gone.

The fix at that point it to revert the revert changeset. But the real solution is to never revert a merge.

Possibly that `git revert` doesn't somehow remove the commit you've done, rather it creates a new commit removing the changes, along with a commit message saying which commit is being reverted.

I don't think it's specifically about reverting merge commits but rather the fact that "git revert" is quite different from "svn revert" which may not be immediately clear and may not meet everyone's understanding of the term "revert" - which is to say, it does not simply "get rid of" the unwanted commit but rather creates a new one that has the net effect of undoing that commit's changes.

I keep meaning to make an alias for it called "git anticommit".

As well as what my sibling comments said, it is also a reference to The Princess Bride.

Would you like to know more? http://knowyourmeme.com/memes/you-keep-using-that-word-i-do-...

Nice chart, at least for a reminder of the command you're likely to need. However, "Is it already on GitHub" should be "have you already pushed it publically". Reminder: git is distributed.

Git is distributed indeed, but good writing style prefers specifics to abstract generalities. It's better to use Github as your example and expect the reader to understand - or if appropriate, explain in a separate paragraph - that there are other options for public repositories.

Great tool for young interns! :D

I think there is a small mistake though, for the "I accidentally commited something": the answers yes and no for "Has anyone else seen it?" are inverted.

Hmm, I don't think so. The answer for "yes" is to do a `git revert`, which does not modify history. Instead, it creates a new commit.

The answers for "no" all involve modifying history, which I think is generally perceived to be quite OK so long as you aren't modifying history that is public.

yep you're right and the question was already answered in the comments. :)

SO useful, thanks!

This is an area where I get completely lost with regard to the 'right' thing to do to fix things up.

There should be a section for git filter-branch.


git is only good for people that was working like Linus. if you didn't have been accepting patches by email but instead had a fluid svn, perforce, etc central repository and people already collaborating with commit powers, then if you move to git "just because" (which is the reason of 99% migrations) you're going to have a bad time.

sadly, my company decided to move just to use pull requests as a poor man's code review tool. sigh. I'm the 99%

Sounds more like resistance to change than anything wrong with Git. I used perforce at my previous company, and while Git's learning curve was higher, I definitely see the advantages of a distributed version control system over a centralized one:

1. Not having to check out files means I can work offline.

2. When working on multiple features, it's much easier to create a new Git branch than it is to create a new Perforce workspace.

3. People really tend to abuse Perforce's 'lock file' feature. I'm glad this isn't possible in Git.

4. I haven't really noticed any drawbacks to the pull-request feature. You can still review and comment on diffs on Github.

5. It's the version control of choice for open source software, so if you use any third-party libraries (and I hope you do!), you'll probably need to know how to use Git anyway.

I can't really think of anything I miss from Perforce.

Edit: these advantages are not specific to Git, but any distributed version control system. If you find Git to be too difficult, don't worry, it's not the only game in town. I've heard Mercury is much easier to pick up. Good luck!

love how git people like to shout "afraid of change"

i known it's the open source favorite. because it solve that problem.

for me all my corporate projects where in hg before git became a fad. but i guess I'm afraid of change/can't read a manual.

>>love how git people like to shout "afraid of change"

Only when you don't give any substantive reasons and just talk about how difficult it is. It just seems difficult because it's a different way of thinking.

>>i known it's the open source favorite. because it solve that problem.

So you do agree that it solves a real problem, it isn't just a fad. Also, a lot of companies like to attract good talent by open sourcing some of their internal libraries. Since they'll be using git for that anyway, makes sense to use git as their main VCS.

>>but i guess I'm afraid of change/can't read a manual.

You're taking this way too personally. I'm just saying give it a fair shot and come up with objective problems with it. No one will take you seriously with "I don't like it because it's too hard". You're better than that.

Why would you need to know how to use any version control software at all to use a third party library? I mean, I do both, but haven't really seen a connection.

Before git-based package managers became the norm, it wasn't uncommon to track/update dependencies manually using command-line git.

Also "using" a third-party library hopefully results in finding bugs, fixing them, and submitting a pull request to the project.

> Before git-based package managers became the norm

When did using git-based package managers become the norm?

> it wasn't uncommon to track/update dependencies manually using command-line git.

Are you saying you normally update your third-party libs with the latest from HEAD instead of using versioned release artifacts?

(I'm guessing you're speaking from a JS dev perspective?)

> When did using git-based package managers become the norm?

I'm a web developer, so my response was hastily written thinking about my own narrow scope. I'm sure that non-web developers can go their whole lives without interacting with git, but it's impossible for web developers.

Npm (Node), Composer (PHP), and Bower (web) package managers all use git (and often GitHub itself) pretty religiously. I know that one or more of those may support other VCS repos, but git is the de facto flavor.

> Are you saying you normally update your third-party libs with the latest from HEAD instead of using versioned release artifacts?

Not exactly. First of all, that's what I _used_ to do before every language had its own package manager.

Second, I do use versioned releases. However, I use the tagged versions that are determined by the author(s) of the library. I'm not just pulling down a bleeding-edge, un-tested library, and I don't get every single commit.

I wasn't aware that git-based package managers were the norm, but I've used third party libraries in two different ways.

1. Nuget packages inside Visual Studio 2. Download the library using a web browser, and just put it where it needs to be.

I'm sure some people would scoff at this list, but it does demonstrate that you can certainly use third party libraries without using git.

> 2. Download the library using a web browser, and just put it where it needs to be.

That might work for certain projects, but let's say you're using 10 third-party libraries. If they're under active development, you can expect at least a few security updates between the time you first import them and the time you ship your own product.

It's not very practical (especially for a programmer!) to keep manually checking your dependencies' product pages for updates.

If you want to look at the commit history or submit a patch, you'll need some sort of version control.

That is by far a minority of my uses of third party libraries.

Man, sounds like the complete opposite experience to me. Going from SVN to even a centrally controlled Git repo is a breath of fresh air.

I recently switched a project from Darcs to git. It was (again) mostly centrally contained, despite being a DVCS. And Darcs being DVCS, we held out on switching to Git since it seemed like it wouldn't really be that much of an improvement. In other words, change for change sake.

Boy was I wrong. Even that change was refreshing. I find Git to be an absolute pleasure to use (and as a plus it stole all the good Darcs interface features). Git made managing our release branch fun again. The thing I like about Git is that it's low level enough that you can make it do anything.

Like the time I foolishly changed the EOLs on upstream code after I committed it—Git let me track my changes and merge in new upstreams, despite every line in the new upstream being different. Yay, git.

What are the improvements of using git over darcs? Do you miss anything from darcs?

Darcs doesn't support branches—it's just a collection of patches in every repo. Our Darcs project was set up with a "dev" repo where we'd dump everything and then promote patches to "beta" repo and then the "production" repo. The downside was that "dev" was filled with a lot of dead end patches that needed finishing/fleshing out before they could go to production. In git, those are now on separate branches and so the main development line is much cleaner. We could have done that with Darcs, but it would require multiple repos (one for each branch), both on the server and on our development machines (yuck).

The first thing we did after converting the Darcs repo to Git was to run a complicated rebase script that split all the dev repo patches into logical git branches. If you looked at the Git repo at that point it would be a single linear set of commits which then explodes into 14 or 15 different branches all at the same point.

Since then we've been using feature branches to do our development and Git really helps to keep distractions to a minimum. "git stash" and feature branches mean that random stuff I am trying is filed away neatly and doesn't pollute my working directory like it did when we were Darcs based.

Honestly I don't really miss anything from Darcs. I could fib and say Darcs's cherry-picking is better than Git's, but while that's true, I don't really cherry pick much in Git (it's usually only to fix accidental checkins on the wrong branch) and so I don't hit conflicts often (at all, really).

Darcs allowed us really simple deployment (we'd just push our patches to the live server—not the cleanest, but oh so easy). Git required us to write a hook that deploys when we push to the production branch. However, that was actually a blessing in disguise, since now the hook can do good stuff like reload the server when the code changes and rebuild static assets as appropriate. We used to just do that by hand.

If working like Linus means using git, then I'd say his is a better way to work. Speaking for myself, there's no reason I can see to ever go back to svn. Even for personal single-dev projects.

It is so simple to create a new git repo on the fly, with no need for a separate repository location. And rebasing plus easy branching has changed the way I work forever. Git allows you to commit early and commit often, safe in the knowledge you can always reorder, combine, remove and/or re-comment your changes later.

This frees you to experiment without worrying about losing the progress you've already made. If you reach a dead-end, it's easy to go back and start working in another direction, while saving the branch in case you change your mind.

Basically, once you get past the learning curve, git makes it extremely easy to remain in that most blessed of version control state of having no uncommitted local changes. And once you've saved with with a commit, it's pretty hard to permanently lose it.

at least, before you push changes to another repo, if you're doing that.

Considering that there are multiple widely used code review systems based on git that aren't based on pull requests, I can safely say your premise is null and void. Not to mention I can't quite parse the broken grammar of your second sentence.

> my company decided to move just to use pull requests as a poor man's code review tool

Using Git, and using pull requests as code reviews are two very separates things. Many people addressed the first point (e.g. Why git is totally fine), so I'll focus on the second one: code reviews with Git. Pull requests is one of many ways to do it, which I personally find difficult with bigger teams working on non open-source projects. I'd recommend looking at Phabricator as a code review tool that works really well in teams.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact