Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some experience sharing about keeping a linear git commit history #461

Closed
fangpenlin opened this issue Aug 8, 2013 · 9 comments
Closed

Comments

@fangpenlin
Copy link
Contributor

Although the issue is mentioned in #415, I see there are some long developing (log page relative) commits are merged. And still, the git commit history is too complex to read in that situation:

2013-08-08 1 26 20

This is not the worst git commit history I have seen, but I think we can do better on this. I can share some of my experience here.

Use SourceTree

I use SourceTree to manage my git repos, it is really nice and handy to use. I really love it. ❤️ I never like hard-to-memorize command line tools and those ugly ASCII log graph. Here is the website

http://www.sourcetreeapp.com

It's free, and even better, it supports both Windows and Mac.

2013-08-08 1 39 20

Some daily routines

Always create a new branch on new feature or bugfix

I always create a new branch on new features or bugfixes. Some naming practice could also be used, but so far, this project is not that complex, it won't be necessary.

2013-08-08 2 04 04

Next, start working. To submit a commit, just click the commit button and type your commit message

2013-08-08 2 09 56

(Tips: you can drag files to add them into the staged list just like git add did)

Then, push to our fork repo

2013-08-08 2 14 51

So far so good, we have a nice and clean history with a feature branch

2013-08-08 2 21 04

For now, we want to merge it, but we want to keep the branch history, so remember to disable fast forward merge option.

2013-08-08 2 19 10

It's time to merge, first, right click one the master branch and click Checkout. You should be at master branch now. Then, right click new-feature branch and click Merge.

2013-08-08 2 26 05

Remember to check Commit merged changes immediately to make a new commit directly.

Whoa, here we are, a beautiful linear history still with branch information. The most merging might be done in GitHub, when you click merge pull request it do almost the same.

2013-08-08 2 44 30


okay, this is too long, I am going to post the remaining parts in following posts

@fangpenlin
Copy link
Contributor Author

Some adventure

You then continue on the next awesome feature - foobar-2000!

2013-08-08 2 49 28

Things go well, however, in the mean time, a new branch is merged from other guys repo. Oh my god, foobar 3000! awesome!

2013-08-08 2 58 20

Okay, let's see what it looks like to merge it directly

2013-08-08 3 00 28

Ugly, let's try something better - rebase. First, right click on foobar-2000 and click checkout. Then right click on master and click Rebase

2013-08-08 3 05 55

This is better! And we can merge it like before

2013-08-08 3 09 08

@fangpenlin
Copy link
Contributor Author

Some ugly

As usual, you keep work on this nice and beautiful linear history, however, you won't feel safe to leave your commits on your local machine will you? We always push our working branch to GitHub to keep it safe and get reviews and feedbacks from others

2013-08-08 3 39 12

Yes, again, you may hate this, there is another branch is merged into the master.

2013-08-08 3 47 42

Okay, you said, this is not a big deal, I can always rebase and merge as usual. Here you rebase

2013-08-08 3 49 17

Well, it is still under development, you want to push to your fork, but not to merge it. Then you push, and oops!

2013-08-08 3 50 42

So what just happened?

As you can see there is a branch origin/foobar-bugfix, that the HEAD in your origin remote, which is, your GitHub fork repo. When you are pushing your local foobar-bugfix to the fork repo, it means the remote one will be overwritten. It is a little bit dangerous to overwrite a HEAD in Git repo. So, it doesn't allow you to do this by default.

Again, it has risk, so you need to be sure what you are doing (although the commit will still stored in the repo, but without HEAD you cannot find them easily, you will need some low level operations to get them back). In this case, we just want to rebase our commits on the master and push it to our own repo, that won't be a big problem in most cases. It appears SourceTree doesn't support --force push, so you need to click Terminal button. Then type

git push origin foobar-bugfix -f

This will force git to push your local branch to overwrite the remote one. Let's see

$ git push origin foobar-bugfix -f
Counting objects: 11, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 809 bytes, done.
Total 9 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
To /Users/VictorLin/foobar_fork
 + 178c9a4...cc5d760 foobar-bugfix -> foobar-bugfix (forced update)

Here we are

2013-08-08 4 01 28

(Tips: you can click Repository and Refresh Remote Status to update your git history status on the UI)

When you are the only one working on the branch, it is fine to do a force push. For more details, please reference to
http://git-scm.com/book/ch3-6.html#The-Perils-of-Rebasing

@fangpenlin
Copy link
Contributor Author

Always rebase current developing branch when there are new commits

As you know, there would be conflicts when you are doing merge or rebase. When there are more new commits in the master branch, the more likely you are going to have conflicts. So, it is a good practice to always rebase your working branch on the master when there are new commits on it.

2013-08-08 4 19 32

However, sometimes, you have some works on the branch, but they are not committed, you don't want to commit something in middle like this. But when you are doing rebase, Git won't allow you to have change to files in the workspace. In this case, you can use Stash. Click Repository and Stash Changes.

2013-08-08 4 24 16

Then you can see your stash appears in the sidebar

2013-08-08 4 25 36

After you finish the rebasing, you can right click on the stash and click Apply Stash, then here you are. Your saved changes are back to working space.

Again, happy ending 😃

2013-08-08 4 31 48

@fangpenlin
Copy link
Contributor Author

Black magic - Use interactive rebase to clean dirty commits

People make mistake. Sometimes there are small commits which are for formatting or fixing typo. And these commits are all based on your own newly submitted commits.

2013-08-08 4 46 04

In this case, you might wonder would it be nice to adopt some black magic to make your stupid mistakes disappear? Well, yes, there is magic. You can use interactive rebase to squash some commits into pervious one. Now, you are at awesome branch, right click on master branch, then click Rebase children of xxx interactively. Then you will see interface like this

2013-08-08 4 49 55

Select those mistake fixing commits, and click Squash with previous. And you will see multiple commits to be put altogether. And you can click Edit message to modify the commit message of the squashed commit.

2013-08-08 4 51 18

Then press OK and look this!

2013-08-08 4 54 09

Just like what he said in Mad Man, nothing happened!

This is actually even more powerful, you can arrange order of commits around, edit commit messages, delete specific commits. But be careful, like what Spider Man told you

Great power comes great responsibility

It is kind of history rewrite, it is fine to use it on the branch only you are working on, you should not use it on a shared branch unless you know exactly what you are doing.

@fangpenlin
Copy link
Contributor Author

The benefits of linear history

That's it, the history is linear, another wonderful day.

2013-08-08 5 01 31

Well, you may ask what kind of benefit we would have to keep a linear history. Good question.

By doing this, you may can get a cake 🍰

...
...

No, there is no 🍰 Ha ha

That's better than a cake. It is very easy to read what is going on in the history, you can know exactly what branches are merged. Also, there are only merged commits left on the master branch. This means, when something goes wrong in one branch, you can always rollbacks to previous workable merged commit in the master. Or you can always revert one merged branch which has some serious problems easily.

Hope this could be helpful 👍

@matin
Copy link
Member

matin commented Aug 8, 2013

@victorlin does this mean that we should be manually merging PRs by pulling in the committer's branch locally, rebasing, and then pushing instead of using Github's auto-merge?

@fangpenlin
Copy link
Contributor Author

@matin It doesn't have to be done in committer's branch locally, you can do it in anyone's repo, rebase it and push with force argument.

However, the point of doing this is to ask committers to keep their commits based on the latest master commit. Every morning you start to work, the very first thing might be to check are there new commits and rebase your own working branch on it. In that way, maintainer of the Github repo doesn't have to do the rebase, just click the merge pull request button.

@matin
Copy link
Member

matin commented Aug 9, 2013

@victorlin makes sense

@kleinsch
Copy link
Contributor

We're doing this going forward. Thanks for the good info, @victorlin !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants