Robdll
Robdll

Reputation: 6255

How to keep a clean git history

as part of my job i use to make deploys between our enviroments dev/test/prod

We use to manage our code with the well known branching flow, so we have the following branch:

dev -> where all branches get merged to as a single commit when a feature is implemented

test -> where we use to test our code by using the platform

master -> this branch is actually used only for creating tags which will be then used in our production server

Recently i wanted to find a way to keep the code history as clean as possible, but i'm struggling on how to do that easily.

i created a repository and reproduced a flow so that you can understand why i'm struggling

so, after the initial commit i created the 2 branches dev and test and switched to dev to make the following commits and made 3 commits:

9e76b6d - koop4: added anawesome feature that makes life easier

44976b1 - koop4: added anawesome feature that makes life faster

64ea9d3 - koop4: added anawesome feature that makes life brighter

I made a pull request to bring those feature in test and squash-merge them with a singe commit. I also like to paste as a comment the results of the git command

git log --pretty=format:"%h - %an: %s"  test..dev

This leads us to this test History

Sometimes it happens that more features go through this cycle until everything is ready for production. Let's avoid redundacy and let's move to prod with another pull request!

Note: in prod we use to use as commit message the tag name

We did it! We now have a super clean history in all our environment! Great!

master history

So, what's the poblem? Let's now repeat the cycle by adding new commits in dev:

ca215e8 - koop4: this will make you shit your pants

9e76b6d - koop4: added a scary feature that make us freak out

let create the pull request and ...Wait...what??? Why does it says i m still missing these commits:

enter image description here

Ok ok, I understand the concept, but a this point I think you realized my struggling. To keep my history clean i have to pick by myself the commits i need: enter image description here

and even repeat the process for our master pull request.

In the end with some plumbing i can get to a great history for all enviroments, but when things start to grow i struggle understanding which commits i have to put in the commit comment to keep it clean.

Is there anyone with suggestion to keep a clean history without having to struggle that much?

Upvotes: 0

Views: 1024

Answers (1)

torek
torek

Reputation: 487725

Half the problem is that you're using the GitHub Web GUI interface. :-) (I'm half-kidding about this being half the problem,1 but in fact, it's hiding an important detail.)

The other half of the problem is that you are using a so-called "squash merge", which is not a merge. See this answer for details.

When you do use a squash "merge", the effect is that you must abandon the commits that are now squashed. Those old commit(s)—there may have been many, as is the case with the three in your example—have been supplanted by a single new commit. (You can and should then fetch that commit into your own Git's origin/test, since you made it through the GitHub GUI interface rather than the more sensible method of making it in your own repository, on your own test branch, and then pushing that new commit directly.)

How to do this with the GitHub GUI

One easy way to abandon those commits is to abandon your own test branch entirely, e.g., just delete it. Your Git won't know that this is a safe thing to do, so you would have to force-delete it. You would also have to be on some other branch, since you cannot delete your current branch. Then you can create a new branch using the same name test, but pointing to your updated origin/test as its upstream. Now you have in your local test the single replacement commit (and all earlier commits) instead of the three commits (and all earlier commits).

That particular method requires at least two, and usually three Git commands, though: git checkout dev (to get off test), git branch -D test (to dangerously and forcibly delete test), and git checkout -b test (to re-create test). You can use just one dangerous Git command instead: git reset --hard origin/test (again, after running git fetch to get origin/test updated).

How to do this without using the GitHub GUI, safely

All of the above is annoying and unnecessary. Simply avoid the GUI. When you have the test branch working the way you want, do your own interactive rebase, and squash all three commits into one

$ git rebase -i

Edit the three pick commands so that the first is pick and the last two are squash, write the file, and exit the editor. Then in the new editor session, edit the commit message into the "nice" (single-commit) version. Note that there is no need to keep the raw hash IDs of the original three commits—they will never be useful in the future—nor even any of the text messages from those commits: you can construct an all-new, improved commit message.

You will now have, on your own test branch (and nowhere else), the squashed commit. You can now git push origin test to push it to the GitHub repository.

You will also have to do something to kill off your outstanding pull request as being closed by the pushed replacement commit. Since I don't use GitHub that much, I'm not sure what that is. It might be as simple as including "closes #XX" in the commit message, or of course you can do it manually through their Web GUI.


1Does this make it 1/4 of the problem?

Upvotes: 2

Related Questions