This content originally appeared on Level Up Coding - Medium and was authored by Sean Chok
Software developers use version control everyday, and Git is the most adopted tool out there. In fact, the mastery of Git has become essential training for people in the industry. Yet I find many computer science students (especially from my school) lacking this basic skill because their curriculum does not expose them to industry-level software collaboration even though there are various projects requiring them to code in small groups.
One of the biggest Git misbehaviors I have observed is that many students complain that working on different Git branches is difficult and time-consuming. They are afraid of merging commits together because they often encounter merging conflicts that are non-trivial to resolve. If they really have to merge branches, they often use a “hacky” and less sustainable approach which is to force merge, then fix code conflicts manually, and finally make a fix merge conflict commit. This is quite inefficient, and is usually not a pleasant process. The other issue is that everyone else on the team would have to try to merge with the merged branch, and by doing so they would repeat the cycle.
What I would like to bring to the table is a powerful Git utility that has often flown under the radar for these students. Its called Git rebase.
Mastering Git rebase is the key to unlocking the true potential of version control.
Git rebase is capable of many wonderful things. But I believe its core function is to be able to rewind a set of commits, make changes to each commit as the programmer likes, and then put them back together.
To illustrate how Git rebase works, I’m going to show it with an example.
Let’s say you are building a new “Blue Button” for a react app. You started your work by creating a new Git branch called blue-button from the main branch. And you made new commits to blue-button as you built the feature out for a few days. In those few days, other people working on the project created other new features, and merged those features to the main branch. Realizing that your blue-button branch is now behind the main branch, you want to synchronize the changes between blue-button and main. If you try to do a git merge you may encounter conflicts because you may have modified some parts of the code base that other people have also modified.
So instead of Git merge, you use Git rebase. While in the blue-button branch, you invoke Git rebase against main.
git rebase -i main
This is the interactive rebase console, and there are many available options for each commit to follow. Since you want to keep all of your new blue-button commits, you can just pick all of them. This is also the default option for every commit.
At the beginning of the process, Git rebase would temporarily “lift” all of your new commits in blue-button against the last common commit between blue-button and main, and put them on a temporary stack.
Then, Git rebase copies all of the new main commits that other people created, and pastes them onto blue-button. So now blue-button and main share an identical commit history.
After that, you ask Git rebase to pick all of your commits in the temporary stack to replay them back onto blue-button one by one. That means, every such commit would be re-created on the branch, resulting in entirely new commits. You may observe that replayed commits have new commit sha tags. But now the blue-button branch is no longer behind the main branch, and so subsequent merging would not cause any conflicts.
The result is simple and elegant because there is no need to create additional merge commits.
But if you pay close attention, you might start to wonder that if the new main commits do have some modifications on code that the new blue-button commits also do, merge conflicts should still be observed. That’s correct! Such conflicts would be seen when the new blue-button commits get replayed onto the branch.
In this case, when a conflict is observed on a certain blue-button commit. The Git rebase process is paused, and Git would ask you to resolve the conflict before continuing.
You would have to go to those specific pieces of code to fix the issues (hopefully without too much effort if you and your team follow good software engineering practices).
After the conflict is resolved, you can ask Git to continue the rebase process.
git rebase --continue
The original commit is modified, and recreated into a new commit that is now free from conflicts with the new commits coming from main. The result here is also beautiful because you don’t need to make any unexpected fix merge conflict commits.
Alternatively, if you believe that the rebase process has gone wrong, and you can tell Git rebase to just abort it entirely.
git rebase --abort
Then your blue-button branch would revert to what it was before Git rebase.
Pro tip: you can run git status during the conflict resolve pause to check where you are in the commit history. It will also give you some options about what to do next.
If you learn how to use Git rebase, you may soon find out that it is more than just a tool to keep branches in sync (like what I’ve just shown). It allows you to have better control over each commit like amending commit messages (reword), and deleting commits entirely (drop). You can also plan for the replay process to be paused (break) for specific commits so that you could inspect what the code base is like at that point in the commit history.
Git rebase is my go-to solution when it comes to solving issues with versioned code bases. For example, I would often make a commit onto the main branch only to realize afterwards that the commit should have been on a new branch. So I would create a new branch from there, then checkout to the main branch, and rebase it against the previous commit. In the interactive rebase console, I would drop that specific commit, removing it from the commit history of the main branch. I know that in this case you could just do a git reset --hard <previous commit sha>, but I simply wanted to illustrate that Git rebase could achieve the same commit deletion function as well.
To conclude, Git rebase is a mightily versatile tool, and having it in your software engineering toolbox would surely benefit you.
Level Up Coding
Thanks for being a part of our community! More content in the Level Up Coding publication.
Follow: Twitter, LinkedIn, Newsletter
Level Up is transforming tech recruiting ➡️ Join our talent collective
A verstatile Git utility that reduces the pain of resolving merge conflicts was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Sean Chok
Sean Chok | Sciencx (2022-06-23T02:10:10+00:00) A verstatile Git utility that reduces the pain of resolving merge conflicts. Retrieved from https://www.scien.cx/2022/06/23/a-verstatile-git-utility-that-reduces-the-pain-of-resolving-merge-conflicts/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.