DEV Community

Cover image for Do up your branch before merge.
Manuel Artero Anguita 🟨
Manuel Artero Anguita 🟨

Posted on • Edited on

Do up your branch before merge.

Cover Image: Puppy Bath Time! by pixel artist Andrea Zevallos - @SazdxHikari


Finally! My feature is ready for review. Now I'm opening the PR… but hold on!🚨📰
Ponder the question: How does your branch look like?

$> git log --pretty=format:'%h - %s' main..feature/drag-n-drop-grid  
f6dec33 - chore: revert tsconfig 
ee409e7 - revert DragDropWrapper (recover prev. code) 
7dfcee2 - fix ci 6a84dd7 - testing 
d14ffee - new component <DragDropGridWrapper /> 
914cca3 - wip 
8796b3e - feat: replace internal library for <DragDropWrapper /> 
f6ad24c - chore: review .eslint + tsconfig 
7da219e - new dependency 'react-draggable-tags'
Enter fullscreen mode Exit fullscreen mode

That 'WIP' commit? sure I wasn't into writing a message; the 'fix-CI' one? I didn't expect it to occur; the 'revert' over there? yep that was causing too much trouble 🤷‍♀ .

Development process has these steps back. You start coding with some idea in mind; maybe you change the approach while coding; maybe you add some extra - not 100% related - boy-scouting; maybe you reinforce the coverage of a piece you're to use, etc.

Thing is, final history might look better when merging it to master. git allows us to change the past, and pretend you did nailed it from the beginning.

All we need is the Gem of Time

$> git rebase --interactive main
Enter fullscreen mode Exit fullscreen mode

Marvel's Dr. Strange practicing time control using an apple

Our example branch

Before messing up with time traveling, let's schematize our feature branch.

Schema for our example branch as a graph

  1. Add new dependency to the project
  2. Unrelated change to eslint and tsconfig config files
  3. Start the feature itself: change the internal implementation of a React component 4, WIP (continues commit #3)
  4. Here we change the approach: instead of changing the existing component (prob. we'll mark it as deprecated at some point), we decided to create a brand new component.
  5. Tests for the new component
  6. Fix CI (continues commit #6)
  7. We recover the original component (using get reset) keeping both components in the project.
  8. Revert tsconfig change from commit #2 (prob. it was causing more noise than expected

Baby Steps

1. Don't panic.

Remember that once you've committed, you can't lose your work(*).

You may save the reference (the hash) of the top commit. This can be used as a panic-button any time to get back to the initial situation.

$> git reset --hard <ref>
Enter fullscreen mode Exit fullscreen mode

(*) there could be extreme situations like loosing the hard drive or zombie apocalypse 🧟 but you get what I mean.

2. Start squashing (s) any 'WIP' and 'Fix prev. commit' to their parent.

previous graph were we're squashing commits #4 & #7

Change the word pick by s for those commits. In this example:

 git rebase --interactive main
pick 7da219e new dependency 'react-draggable-tags' 
pick f6ad24c chore: review .eslint + tsconfig 
pick 8796b3e feat: replace internal library for <DragDropWrapper /> 
s 914cca3 wip 
pick d14ffee new component <DragDropGridWrapper /> 
pick 6a84dd7 testing 
s 7dfcee2 fix ci 
pick ee409e7 revert DragDropWrapper (recover prev. code) 
pick f6dec33 chore: revert tsconfig
Enter fullscreen mode Exit fullscreen mode

When squashing (s), you'll be prompted for the resulting message. In this case we'll discard commit message #2 both times

screenshot of the rebase console

3. Place together (move) every related commit.

In this example, we're moving the top-most commit to be right after it's counterpart. Besides, we're squashing the testing commit to its parent.

previous graph were we're squashing commits #4 & #7

screenshot of the rebase console II

4. Keep squashing

Now that we have these 3 - let's call them - 'sections'. Seems fair that we can squash one last time.

final schema where finally there are just 3 sections

Note: with rebase you may get merge conflicts (exactly the same way you face conflicts with git merge). 
My recommendation is to keep focused on "How will this code look like in the final picture?"; pretend you did nailed it from the beginning.

5. Finishing touches 💅. Take the chance to reword (r) commit messages. 

Personally I use Semantic Commit Messages. But we can cover that at another time.

This is our branch after taking a bath 🧽. Much better right?

$> git log --pretty=format:'%h - %s' main..feature/drag-n-drop-grid
a3f5f33 - feat: new component <DragDropGridWrapper />
f6ad24c - chore: review .eslint
7da219e - chore: new dependency 'react-draggable-tags'
Enter fullscreen mode Exit fullscreen mode

TL;DR

  1. Don't panic. Once you've committed, you can't lose your work. You may prepare a panic-button copying the hash.
  2. Squash (s) any "WIP" and "Fix prev. commit" to their parents.
  3. Place together (move) every related commit.
  4. (If applicable) keep squashing.
  5. Reword (r) commit messages.

- Thanks for reading 💚.

Top comments (2)

Collapse
 
ariera profile image
Alejandro Riera • Edited

This is a great summary of a rather advanced approach to git.
I had only used rebase in the past for fixing nasty problems, but never to tidy up my code before sharing / pushing. I think it's an excellent idea and use of the feature and I will try to incorporate it into my workflow. Thanks for sharing!
Also, great write up, straight to the point, and with useful illustrations! :-o

PS: I'd love to hear more about these Semantic Commit Messages

Collapse
 
manuartero profile image
Manuel Artero Anguita 🟨

Thanks for the nice words! really appreciated.

Yep! planning to write a post about Semantic Co Messages... there are already posts about them but I think I can share one idea or two :)