Live data from Hacker News

Linus on keeping a clean git history (2009)

mail-archive.com

41–50 of 86 posts

Re: Linus on keeping a clean git history (2009)

#41

So I'm relatively new to version control entirely, but in the last few years my group has been making a big push to institute Git. I have been wondering lately, however: how much history cleaning is expected/desirable? When I develop, I split my commits into as many small changes as I can so that the commit messages are single topic. I thought that was basically the idea. Every once in a while I use rebase to combine…

> I have been wondering lately, however: how much history cleaning is expected/desirable?

After you've published your work and someone else has checked it out, you don't want to touch your history unless there is a serious problem.

But when you're working on something, you can commit all you want, and do many commits. Then at some point you put your work up for reviews and get feedback. Then you fix the feedback and commit as many times you need to. When your code is good enough to be merged into master, you should clean up the history a little with rebase.

You should at least try to squash and rebase your commits so that there will not be any commit in the master history that is completely broken. The whole point of having a history is that you're able to go back. E.g. you might want to search the point in history where a problem originated (git bisect can automate this with a "binary search"). You cannot effectively do that if your history is full of commits that do not work (E.g. won't build or will crash all tests).

To recap: never change published history unless there is a serious issue (like you committed your database password to github). But you can and should change your local history before you publish to master so that there are no broken commits that make it difficult to walk back in history.

Re: Linus on keeping a clean git history (2009)

#42
post #22

Earlier quoted context omitted.

In my experience, git is more complex than svn, but not needlessly so. In any sufficiently long-running project, I've wanted features that git has and svn doesn't.

As a relative newbie to git, Why do I get prompted to enter a commit message when I'm just doing a git pull? Why do I have to explicitly add every file I want to commit each time? Why can't it just default to "everything under the current dir" like svn does?

If you have commits in your local branch and you are doing a pull without --rebase you can get merge commits, but I believe those messages should be generated for you(?). I almost always choose rebase over merge so there are no merge commits, all my merges are fast forward. Check your workflow.

Regarding your second question, you want "git add -a". Git gives you the ability to commit "some of what I've changed here", even within files (see git add -i). This facilitates clean commit history by letting you control exactly what is in each commit (even if you changed other files).

And even once you've made your commits to your private branch of course you can continue to change the order of them or combine them with interactive rebase... until you push...

Re: Linus on keeping a clean git history (2009)

#43
post #22

Earlier quoted context omitted.

In my experience, git is more complex than svn, but not needlessly so. In any sufficiently long-running project, I've wanted features that git has and svn doesn't.

As a relative newbie to git, Why do I get prompted to enter a commit message when I'm just doing a git pull? Why do I have to explicitly add every file I want to commit each time? Why can't it just default to "everything under the current dir" like svn does?

Why do I get prompted to enter a commit message when I'm just doing a git pull?

Because `git pull` == `git fetch` + `git merge`. If there are upstream commits you are fetching that are not ancestors of your head commit, then pulling involves merging the divergent history, thus creating a new merge commit. And a merge commit, like any commit, needs a message.

Why do I have to explicitly add every file I want to commit each time?

Because Git has an intermediate staging area (the "index") between your working directory and the committed history. This is a great feature; one of the most useful aspects of Git, in fact. The side effect is that you must add your changes to the index before committing, but this is a small price to pay for the huge increase in flexibility the index affords.

Why can't it just default to "everything under the current dir" like svn does?

You can do `git add .` to add everything in the current directory without naming it all explicitly. Or you can use the `git commit -a` shortcut (and similar -A and -u options) to add and commit in a single command. This is hardly a significant increase in effort over `svn commit`.

Re: Linus on keeping a clean git history (2009)

#44

So I'm relatively new to version control entirely, but in the last few years my group has been making a big push to institute Git. I have been wondering lately, however: how much history cleaning is expected/desirable? When I develop, I split my commits into as many small changes as I can so that the commit messages are single topic. I thought that was basically the idea. Every once in a while I use rebase to combine…

> However, I could use rebase to start combining loosely related commits, trading the time resolution for clarity in the commit history.

In general, your commits should be the smallest atomic operation that makes sense. When people talk about 'clean history,' they're talking about working in the awesome workflow git provides:

1. Write half-written broken code. 2. Fix that code up. 3. Add some more onto that. 4. Fix a typo! 5. Forgot to update the README.

Now, you could push that to master, but then the main master is littered with commit messages like 'oops' and 'typo.' Instead, you can rebase 5-1 onto the latest master, squash them together, and have one 'nice' commit that only has the cleaned up final changes.

This is one of the most powerful things about git: in a private repo, you can commit all kinds of garbage and half-written stuff without caring. When you want to make your stuff public, rebase and squash, then send it out. Be careful though! Only rebase your own private branches, or you're gonna have a bad time™.

Re: Linus on keeping a clean git history (2009)

#45
post #22

Earlier quoted context omitted.

In my experience, git is more complex than svn, but not needlessly so. In any sufficiently long-running project, I've wanted features that git has and svn doesn't.

As a relative newbie to git, Why do I get prompted to enter a commit message when I'm just doing a git pull? Why do I have to explicitly add every file I want to commit each time? Why can't it just default to "everything under the current dir" like svn does?

> Why do I get prompted to enter a commit message when I'm just doing a git pull? Not sure. The only time this happens to me is when I need to fix a merge conflict. > Why do I have to explicitly add every file I want to commit each time? Why can't it just default to "everything under the current dir" like svn does? "git add ." adds everything below the current directory.

Re: Linus on keeping a clean git history (2009)

#46

So I'm relatively new to version control entirely, but in the last few years my group has been making a big push to institute Git. I have been wondering lately, however: how much history cleaning is expected/desirable? When I develop, I split my commits into as many small changes as I can so that the commit messages are single topic. I thought that was basically the idea. Every once in a while I use rebase to combine…

My workflow when working on a large project or doing multiple commits looks roughly like this:

  git checkout -b featurebranch
  git commit -am "foo"
  git commit -am "bar"
  git rebase master # to update my personal history with public history
  git commit -am "baz"
I've used different flavors of merging it back in, though. Method 1 is to `git checkout master; git diff master..featurebranch | git apply`. Method 2 is `git rebase -i HEAD~10; git checkout master; git cherry-pick featurebranch`. I'm sure there are other and better methods, but those are the ones I've used recently that I like.

After I collapse a branch down into a single commit (I rarely want a branch to become multiple commits), I typically use `git commit --amend` to modify the commit message to something fitting and push it upstream. --reset-author is also good there to properly denote the correct date/time, rather than the first commit you squashed.

Re: Linus on keeping a clean git history (2009)

#47
post #3

This highlights the only thing I don't like about Git. It's an immensely capable tool, but it gives no guidance regarding the right way to do things. Our own teams have a set of practices which are similar but different from what Linus outlines here. And different projects on my company use different practices from those. The worst thing is that there's no way of enforcing these workflows or practices other than out-…

"there's no way of enforcing these workflows or practices other than out-of-band social conventions"

I think this is exactly what Linus intended when he designed Git. He explained in a Google talk the way he controls what is committed to the kernel is by just pulling from people he trusts.

If you try to use git as a centralized version control system you lose control of what gets pushed regardless of how many rules and workflows you setup. Have devs send pull requests instead and don't accept/merge bad commits.

Re: Linus on keeping a clean git history (2009)

#48
post #14
post #13

Earlier quoted context omitted.

I'm not sure exactly what you think a better tool would look like. By your own admission, there are multiple "right" ways to do branch management, and all of them are supported meaningfully by git. But, more or less by definition, a tool that enforced a "right" way to do things would disallow some of these. So... I don't understand. Do you want a tool that makes the kernel branching style illegal, or one that breaks…

It isn't hard to imagine a SCM tool (using GIT internally) that enforces a specific set of curated operations for a particular workflow, that teams could agree to use for a given project. You could have different such tools for different workflows on different projects. You could even write a meta-tool that allows administrators to define and reify a workflow which would then be enforced for developers on a project.

gerrit's permission system goes a good ways in the direction you're talking about. (Unfortunately, it's rather baroque and poorly documented.) You can specify who can submit patches, who can approve them, who can merge, whether a repository allows merges at all or requires rebasing or cherry-picking, etc.

Re: Linus on keeping a clean git history (2009)

#49
post #5
post #3

This highlights the only thing I don't like about Git. It's an immensely capable tool, but it gives no guidance regarding the right way to do things. Our own teams have a set of practices which are similar but different from what Linus outlines here. And different projects on my company use different practices from those. The worst thing is that there's no way of enforcing these workflows or practices other than out-…

> It's an immensely capable tool, but it gives no guidance regarding the right way to do things. Maybe there isn't a "right way". A workflow that suits a simple desktop application is different from what is used by a kernel or another product that has dozens of targets to worry about. Similarly a web app that gets deployed in a controlled environment will most likely need a different way of working than an end-user a…

>The culture around your product is probably very different from the kernel devs' culture so it makes sense for you to have a different model.

I think he meant he wants the ability to enforce a certain behavior within his own group.

Re: Linus on keeping a clean git history (2009)

#50
post #18

Earlier quoted context omitted.

Isn't that what all large projects are doing internally? Hell, big chunks of the git chrome (things like "git am", "git request-pull", "git send-email") is precisely an attempt to write scripts to automate core parts of the kernel workflow. Github added bits of its own, like "watching" a public repository and providing a core spot for pull requests to land, with discussion and review tools. I don't understand why you…

I think it's a balance. There is value in having people working on a given project aligned on the same basic workflow. To achieve that for a team that is currently growing or is planning to grow, you have to document what that basic workflow should look like. That "document" can be a set of social mores that are loosely enforced through complaint and argument, or an actual document somewhere, or a tool like your pare…

I don't disagree at all. But in reality, those tools exist and are all around us. What would be the value of putting that stuff into git itself? Why is it a shortcoming of git that it hasn't picked one?
Post reply on HN