00:00:04.940
I wanted to do a kind of shallow dive into some Git commands using a recent catastrophe that we had on my team. It served as a perfect example because it really illustrates the differences between merge and rebase, as well as fetch and pull. We'll start with this classic visualization where Git version control is basically a singly linked list. We should have a clue with that because the most recent commit is called the head. As you go through coding, you're making a series of commits, and each one of these commits is a snapshot of the whole codebase, including your new changes—not just the differences from the previous version. This detail is important, and we'll circle back to it later.
00:00:22.020
When you have some code ready, you want to merge it into another branch. In the simplest scenario, you're essentially taking that shorter linked list and appending it to the top. Your latest commit becomes your new head. However, when you're doing a rebase, you're treating it like a singly linked list. Git merge, on the other hand, is a totally different animal. When using git merge, you're instructing it to make decisions for you. Git will choose one of six different merging strategies to execute. I don’t have the time or illustrations to explain these different strategies, but I really encourage you to look them up yourself.
00:01:05.939
Fast forward to a few months ago, I was working on a budget application using Rails. At that time, I was the only person working on it, so I was utilizing a rebase workflow. There were a bunch of new features I had developed, and since my test suite was passing locally and had passed QA, I handed it off to someone else to load it into production. Unfortunately, after that, production blew up. I was trying to figure out what happened. I checked the server logs, the Git history, and individual commits while looking through the terminal command history because I couldn’t understand the issues I was observing. The code that existed in the master branch of our repository was not the same code that existed in the master branch in production.
00:02:08.280
What happened? How did I have code that had been deleted or moved weeks or months ago that was still present alongside the new features? Long story short, the culprit was git pull. To be precise, while miscommunication was a significant factor, it's a topic for a different talk. In the context of this presentation, git pull was the technical culprit.
00:02:30.540
When I was first learning about the rebase strategy, I spoke to senior developers about it and asked why I shouldn't use git pull. Their responses were vague, with repeated warnings to avoid it at all costs. Determined to understand, I decided to look it up. I discovered that git pull internally calls git merge. Now my catastrophe began to make sense: I had been using a rebase workflow, and while refactoring and adding new changes, I was altering the commits themselves—resulting in different commit SHAs. This led to an inconsistent history between the master branch in the repository and what existed on production.
00:03:07.860
So if someone ran git pull in production, Git would have to go back farther to find a matching commit for merging, trying to combine incompatible branches as best as it could. Fortunately, it was a relatively easy fix. We addressed the communication issues, but the main change was that we all agreed to use the same script across all environments. We essentially performed a hard reset on production's master branch to ensure its code matched exactly with what was in the repository. While it's an anticlimactic ending, I hope you learned a couple of things that you didn’t know before. If you're a newer developer, maybe you've gained some insights about these tools. Enjoy the rest of the conference, and thank you!