Skip to content

Commit

Permalink
Update git blog post
Browse files Browse the repository at this point in the history
  • Loading branch information
canxerian committed Jul 15, 2024
1 parent f844820 commit aa41a81
Showing 1 changed file with 39 additions and 19 deletions.
58 changes: 39 additions & 19 deletions content/posts/how-to-completely-avoid-git-conflicts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,63 @@ date = 2024-07-15T14:01:23+01:00
draft = true
+++

It's time to say goodbye to git conflicts for good.
It's time to say goodbye to Git conflicts for good.

Let’s understand what causes git conflicts and develop strategies to completely avoid, or at least dramatically reduce encountering them.
Let’s understand what causes Git conflicts and develop strategies to completely avoid, or at least dramatically reduce, encountering them.

First, let’s look at a situation that leads to a conflict.

## Simultaneous edits on the same (main) branch
![Illustration of two developers working off the main branch and encountering a git conflict, part 1](images/git-conflict-illustrated-01.png)

You and a colleague are working on the same branch tracking to your remote git host, (be that GitHub, GitLab or something else). When you checkout the main branch, you both effectively have local copies of that branch - notice that when you commit GitHub (or whatever git hosting provider you use) doesn’t see those changes until you push.
![Illustration of two developers working off the main branch and encountering a git conflict, part 2](images/git-conflict-illustrated-02.png)

You're both assigned tasks to modify `index.js`. Unfortunately, your colleague completes their task much faster and has already pushed their commit to main.
# Simultaneous Edits on the Same Branch e.g main

At a slower pace, you modify and commit `index.js`. When you attempt to push, the remote main branch will reject that command and request that you "pull" (i.e bring your branch up-to-date with remote).
You and a colleague are working on the same branch tracking to your remote Git host (be that GitHub, GitLab, or something else). When you check out the main branch, you both effectively have local copies of that branch. Notice that when you commit, GitHub (or whatever Git hosting provider you use) doesn’t see those changes until you push.

You pull and shock horror, you have a merge conflict!
You're both assigned tasks to modify `index.js`. Unfortunately, your colleague completes their task much quicker and has already pushed their commit to the main branch.

![Illustration of two developers working off the main branch and encountering a git conflict, part 1](images/git-conflict-illustrated-01.png)
![Illustration of two developers working off the main branch and encountering a git conflict, part 2](images/git-conflict-illustrated-02.png)
At a slower pace, you modify and commit `index.js`. When you attempt to push, the remote main branch will reject that command and request that you "pull" (i.e., bring your branch up to date with the remote).

### Solution
{{< callout emoji="💡" text="Git rejects pushes to the remote branch if yours is out-of-sync with it." >}}

You pull and —shock horror— you have a merge conflict!

## Solution

In this situation, had you pulled before modifying `index.js`, the file created by your colleague would appear in your local repo. You could then edit that file and push it back to the main branch.

In this situation, had you pulled *before* modifying index.js, the file created by your colleague would appear on your local repo, you can then edit that file and push it back to main.
So push frequently and pull frequently. However, a better solution is having a separate branch per feature (aka feature branch), e.g., feature/create-index-html, which could help with multiple developers working in isolation. When the feature is ready, it can be merged back into the main branch, ready for other developers to pull.

{{< callout emoji="💡" text="Git always wants you to work off the latest version of the file as hosted on the remote branch." >}}
# Simultaneous Edits on Different Branches, Conflicts on Merging

So push frequently and pull frequently. However, a better solution is having a separate branch per feature (aka feature branch), e.g feature/create-index-html, that could help with multiple developers creating the same thing in isolation. When the feature is ready it can be merged back in to main, ready for for other developers to pull.
You and a colleague both followed my first advice. You’re working on different features, so you create the branches accordingly. However, you both need to edit `index.js` and you both need to add some code to line 10.

## Simultaneous edits on different branches, conflicts on merging
You both merrily made your changes and, as you both have your own branches, you can push and pull with no conflicts!

You and a colleague both followed my first advice. You’re working on different features, so you create the branches accordingly. However, you both need to edit index.html and you both need to add some code to line 10.
However, your colleague merged their branch back into the main branch first (again!!) and now your branch is tracking behind, so you need to merge the main branch into your branch to get up to date (called a sync merge).

You both merrily made your changes and as you both have your own branches, pushing and pulling with no conflicts!
When you do so, you’ll encounter a merge conflict on line 10 in `index.js`. What!

However, your colleague merged their branch back in to main and now your branch is tracking behind so you need to merge main in to your branch to get up to date (called a sync merge).
## Solution

When you do so you’ll encounter a merge conflict on line 10 in index.html. What!
Merge the main branch into your branch regularly (aka sync merge). Had you merged the main branch straight after your colleague’s merge, you’d be completing your work on top of their changes. That is, your branch would already contain their changes and there’d be no deviation from their work, thus no conflicts. The longer the time between your last sync merge, the greater the chance that you’ll work on an out-of-date version of a file and the greater the chance of getting a merge conflict.

### Cherry picking a simultaneous edit from another branch

Cherry picking: you and a developer branch off the same point on the main branch. Developer A makes a change to a file and commits to their branch. At the same time, you’re also working on the same file at the same lines. Days later, during standup, you learn about this change and although your developer friend hasn’t merged their branch in to main, you’d very much like that change in your branch.

Rather than duplicate their code manually in your branch (because that will definitely lead to a merge conflict) you do the right thing and cherry pick the commit, thereby obtaining the commit history which is necessary to avoid conflicts when you merge your branch back in to main.

But you get a conflict anyway! WHAT!

The reason is very similar to the branch merge conflict.

### Solution

Merge main in to your branch regularly (aka sync merge). Had you merged main straight after your colleague’s merge, you’d be completing your work on top of their changes. i.e your branch would *already* contain their changes and there’d be no deviation from their work and thus no changes. The longer the time between your last sync merge, the greater chance that you’ll work on an out of date version of a file and the greater the chance of getting a merge.
Again, the solution is to take changes in to your branch as early as possible, so that when you eventually start working on a file, you build on top of the latest changes.

Another solution is for your developer friend to make smaller, more regular merges with main. IMO cherry picking individual commits across feature branches isn’t necessary (although they come in to their own on release branches) and can be avoided simply merging back in to main early and often.

# Conclusion
Evidently, the solution to completely avoiding conflicts lies in the wierd and wonderful non-engineering realm of talking with colleagues and discussing intent. Sometimes however, the overhead of keeping mentally in-sync with your peers isn't a priority, but at least you can now make the decision to go out-of-sync and thus anticipate conflicts as a matter of choice rather than surprise.

0 comments on commit aa41a81

Please sign in to comment.