Live data from Hacker News

Linus on keeping a clean git history (2009)

mail-archive.com

61–70 of 86 posts

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

#61
post #56
post #21

Earlier quoted context omitted.

Let's compare git to SVN. With SVN your only real option is to commit something that is working, right? If you commit something broken to SVN then you will likely get yelled at. With git, you can make a few changes, then think "hmm that might not be the best way to fix it" do a commit and then rip out everything you just did and do it a different way. Or maybe you Added some instrumentation for debugging the problem,…

Does using rebase or squash leave the history in my local repo and "squash" the commits to a single one in the master? Sorry for basic questions but I'm new to git.

No and yes (respectively). Rebase rewrites the history of whatever branch you are on. Squash converts a merge into a single commit on another branch.

Say you are working on a feature in a branch and have made several commits. Now it's time to clean them up in preparation for a merge. You can either squash the entire branch into one revision into master and create a new commit message (git merge --squash) or you can rebase.

If you rebase, you can use interactive mode (git rebase -i) and rewrite your local history however you see fit. You can reorder commits, remove commits, merge commits, edit commits, edit commit messages, anything. It's extremely powerful and lets you make the history of your current branch into whatever you want it to be. I use rebase -i quite a bit to merge "typo" commits into the original commit. Used sparingly rebasing really helps to keep your timeline clean.

You can also rebase while in master but you should not go older than the newest shared commit (origin's HEAD) nor should you edit other people's code during a rebase.

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

#62
post #30

Earlier quoted context omitted.

I think that for people with an svn background there are three different issues that all hit at once: * distributed rather than centralised version control brings a new set of concepts to understand * git is flexible enough to support many different workflows. This means you have to actually choose one, and choice is difficult especially when you're just trying to get to grips with a new tool. svn has much more of a…

Don't most people actually end up using git in a centralised manner though? eg the rise of github. I can totally see git is ridiculously powerful, and general purpose. I just wish it'd default to what most people want a bit more.

"Distributed" is not the same as "ad hoc". In virtually all workflows, whether using distributed or centralized RCS, there will be a master copy. The difference between distributed and centralized is whether that master copy is the only copy.

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

#63
post #5

Earlier quoted context omitted.

> 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.

The amount of control you can exercise with hooks as well as the features available in repository management systems like gitolite should be more than adequate to enforce whatever policy you may dream up.

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

#64
post #32

Earlier quoted context omitted.

It would be handy if there was a option to git-rebase that would print a warning if you were about to rebase a commit by someone other than $(git config user.email)

I'd suggest writing a git hook on pre-rebase.

One could also write a pre-receive hook on their git server that denies force pushing, so it becomes impossible to overwrite published history. Combined with a gatekeeper approach of denying pushes to the master branch to all developers except an assigned reviewer, this helps foster the idea that unstable code should always remain local and not be published.

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

#65

Earlier quoted context omitted.

> But I'd prefer to keep that history, but rarely use or display it. So why have it? > I'm still new-ish to git and don't get why rebase is popular. My most common use case for rebase is actually to keep my private branches up to date with master. `git rebase master` or `git fetch origin && git rebase origin/master` are common tools for me when I'm doing private work for an extended period of time. This way, I don't…

Because rarely != never?

If you're in the position of rebasing a branch down to a single commit, but many of those commits contain messages that are useful, then keep those messages in the final commit message.

When running an interactive rebase (git rebase -i my_branch~5), you have many options available to you. Fixup squashes and discards the commit message. I'll use this on commits I made that are literally just tags in a commit stream where I'm about to do a destructive action to my code (like during refactoring, you know the ones: 'git commit -m "update"') and I want to ensure I have a point to reset my branch to if I start screwing everything up. Squash just literally combines the commit with the next one, but preserves both commit messages. Use this for commits that are relevant to the named branch you're working on and are descriptive of what the branch was trying to accomplish.

Create a summary as the first sentence of the new commit message. It will show on any pretty-print log message output. Then literally combine all your commit messages into a paragraph (or more) for a detailed description. The information is still there, and it's still in the same place.

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

#66

Earlier quoted context omitted.

> 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…

Okay, that is basically keeping with my current understanding (though I'm not sure how much I live up to the "only have working history in the public repo" rule). There is the other issue I raised, however: is there a good way to group a series of commits that happen to be towards a single distinct goal. Using branches is a clear step in that direction, but it seems like a nightmare to perform a rebase like you descr…

Switching branches is cheap, I'd say the "right" way to get a tree like you want is to have two or even five branches all the time you're working. But I suspect you could make two branches and cherry-pick different sets of commits onto them to get the result you're after. To my mind it wouldn't be worth the effort though; how often do you really care whether the code worked with only 1 and 4 applied?

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

#67

Earlier quoted context omitted.

http://nvie.com/posts/a-successful-git-branching-model/

This is great for people who are that organized. I'm not, so I like the 'just merge everything into master' mentality. See http://scottchacon.com/2011/08/31/github-flow.html

My main issue with the described github-flow is that they push development branches to the server, and encourage that to be done very often.

And my issue with that is once you push something, it's off-limits to any kind of archaeology in the history. And that's not a "principle" thing. If you push your branch, do some rebasing and push again, you are in a world of hurt.

The operation will very likely fail, and recovery is a serious pain in the butt.

If you don't ever do any sort of archaeology, then that's great and it will work for you. I have had numerous occasions where I've tried some git merge or something and screwed things up. I've fixed it by putting my Indiana Jones hat on and digging in.

Being able to tamper with the history has gotten me out of trouble many times. The only time it has gotten me in to trouble is rewriting history that has been published.

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

#68

Earlier quoted context omitted.

This is great for people who are that organized. I'm not, so I like the 'just merge everything into master' mentality. See http://scottchacon.com/2011/08/31/github-flow.html

My main issue with the described github-flow is that they push development branches to the server, and encourage that to be done very often. And my issue with that is once you push something, it's off-limits to any kind of archaeology in the history. And that's not a "principle" thing. If you push your branch, do some rebasing and push again, you are in a world of hurt. The operation will very likely fail, and recove…

which workflow are you referring to?

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

#69

Earlier quoted context omitted.

> 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…

Okay, that is basically keeping with my current understanding (though I'm not sure how much I live up to the "only have working history in the public repo" rule). There is the other issue I raised, however: is there a good way to group a series of commits that happen to be towards a single distinct goal. Using branches is a clear step in that direction, but it seems like a nightmare to perform a rebase like you descr…

So I'm not sure if I understand correctly, but let me put it this way: with a little more git craziness, you can crack apart a commit and separate it into two. This is good if you did two unrelated changes to a file, committed that, and realized you wanted two separate commits later.

The basic process is:

1. git rebase -i, and change a commit to 'edit' 2. git reset HEAD^, this 'undoes' the commit and leaves the changes in your directory as if you had written the code but hadn't committed it yet 3. git status 4. git add -p, this lets you add commits to your file a chunk at a time. first, add all the commits as a part of commit one. skip the parts you want for commit two. 5. git commit (do not do git commit -a here) and write the message for your first commit 6. now your working directory will be all the changes for commit two. git commit -a if you want all of them 7. git rebase --continue

This page[1] has a more concise answer, but leaves out the git commit -p part.

Note that if you mess up in rebase-land, you can always git rebase --abort. If you come out of the rebase and everything looks lost ('oh god I lost my data!'), use git reflog and pull up the hash of where you were before. Your data is still there.

Another note: if your commits are already separate, you can use rebase to selectively squash and reorder them. Read the manual on git rebase -i, if you rearrange commits and only squash some I think you'll get what I'm talking about.

[1] http://stackoverflow.com/questions/6217156/how-to-break-a-pr...

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

#70
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. There is no right way. Think about styling. Is there a right style? No. It is silly to argue over your code's appearance. HOWEVER! As soon as you start collaborating with people and reviewing code, a uniform style is a very nice thing to have. Teamwork creates the need for shared conventions. And that's where your ability t…

If there's no right style, then couldn't the SCM just pick one arbitrarily so I don't have to worry about spending time communicating about something irrelevant to getting the product shipped?
Post reply on HN