Hello, in this article I will speak about reasons why it is important to maintain a history, as well as we will consider one of the ways to do it. This is my first article and I was inspired to write it at Appus Studio, where we also discuss how to work with git and choose the best approach for each project.
When maintaining your history, try to follow these 2 rules:
Master branch should contain only logically completed commits, for example, task A is done or bug B is fixed.
History should not be branchy and confusing with numerous merge commits. In other words, it's better to use rebase instead of merge.
The history of a discrete form, when each commit is logically completed, allows you to work faster and solve problems in the future. For example, you need to do an identical task to task "A" after a while, or you find out that after adding this task, something works incorrectly. You can easily view all the changed files in one commit or checkout to this commit to test if this logic is not in the project anymore or if it has been changed. Also in git, there is a mode to help you search for bugs with git bisect. It helps a developer find a commit in a given range where the bug appeared. If you have a lot of intermediate commits, or worse, if your commits include not compiled code, it is very difficult to use and your development process will be at least 20% slower.
Rebasing instead of merging is better, and let me illustrate it. For instance, I work in the dev branch, for a certain period and I have done 3 tasks (f1, f2, f3), and my colleague Alex has also done 3 (c1, c2, c3).
And then it becomes necessary to put all our changes together and we decide to use merging. If we merge my branches into dev and then do it with Alex’s branches, this is what we get:
Above is the result of only two of the developers committing, so it’s hard to imagine what happens when 3-4 people work on the project and each does several commits in each branch. Obviously, in this case, your history will be even more confusing.
If you use rebase and add up all the branches one by one, you obtain the following result:
But it only is convenient if you rebase a branch with just 1-2 commits, or if you know that you will not have a lot of conflicts with the code that is already in dev. Since the rebase applies commit one by one, the following scenario is possible: you resolve conflicts in one of the first commits, and then in the following commits you have conflicts with the same files that you worked with and as a result, you resolve conflicts with your own code, which is extremely inconvenient and time-consuming. You probably thought that in this case, it is better to use merge after all. The question is controversial and depends on what kind of commits there are in your branch. If they are big and you worked on each of them for about a week, then yes, but if they all relate to some task, then it is better to squash commits by making one commit from this branch, and then rebase this commit to dev.
The question is, what the best choice is, to amend or to reset your commit and only then upload the task to dev with 1-2 commits, or make a lot of commits, and then squash.
It depends on your choice and on the requirements of the project. The fact is that your team lead or customer can ask for daily commits, even if the code is unstable, in order to monitor your progress. In this case, you have no choice but to do squash.
To illustrate, I will create a branch f4 and make 4 daily commits in it from where we started, create a temp branch f4_temp, it will replace the remote origin/f4 for me that I would have created if I worked with a remote repository.
And then squash the commits and rebase.
Now the f4 branch has the same changes as in f4_temp, if you go to the commit settings, you can see that the comments are also saved.
But what if you want to split a task into multiple commits? For example, if you have made internal logic that relates to your task, you want it to be in a separate commit, but it is not yet ready to be uploaded to dev, because you need to finish the UI as well. For example, the f4 branch is internal logic, and as you can see, I have not yet uploaded it into dev, we repeat everything according to the same principle, create the f4_ui branch, and make 3 commits.
Now we squash, upload it to dev, and also keep the f4_ui_temp (origin) branch for the team lead, it can always be removed later.
As a result, we figured out why it is important to maintain the history and how to do it correctly. Thank you for reading, if you have any questions or suggestions, please contact me personally or the company I work at - Appus Studio, helping you will be a pleasure.
Top comments (4)
Thanks for the post and detailed examples. I'm glad you mentioned "the controversial" part, because my experience has been against using git rebase especially when merging new pull requests on master branch. You have listed the disadvantages of rebase clearly, and I think having less error prone git flows is more valuable than the "very" clean history. The history is still clean and its useful to quickly see all code changes by PR when going through the merge commit itself. As for the point of "team lead or customer can ask for daily commits", I find that a weird and unhealthy way of progress tracking (what prevents me doing pointeless commits with low value?). Shouldn't the work progress tracking be done on the Jira tickets instead which has my deliverables listed?
Thank you for comment. They can ask for daily commits to compare logs with code. For example you can log 3 days but real work was in one or two
That's just silly. People could just break down 2 days work to 3 commits, one each day...