Let’s say you’re on a team of coders and you all have access to the same GitHub repo. (One person on the team owns the repo, and they’ve added you all as collaborators18.)
I’m going to use the term collaborator to mean “someone to whom you have granted write access to your repo”.
How can you all structure your work so that you’re minimizing conflicts?
There are a number of ways to do this.
main
, ormain
for each official release.We’ll look at the first few ways in this chapter, but we’ll save pull requests for later.
There’s no one-size-fits-all approach to teamwork with Git, and the methods outlined below can be mixed and matched with local topic branches, or people having multiple remote tracking branches, or whatever. Often management will have an approach they want to use for collaboration which might be one of the ones in this section, or maybe it’s a variant, or maybe its something completely different.
In any case, the best strategy for you, the learner, is to just be familiar with the tools (branching, merging, conflict resolution, pushing, pulling, remote tracking branches) and use them for effect where it makes the most sense.
And when you’re first starting out, your intuition about “where it makes the most sense” might not be dead-on, but it probably won’t be lethal and you’ll figure it out in the school of hard knocks.
“Oh great. Another f—ing learning experience.”
—Actual quote from my mother
Git can’t save you from poor communication. The only way to minimize conflicts in a shared project is to communicate with your team and clearly assign different tasks to people in a non-conflicting way.
Two people shouldn’t generally be editing the same part of the same file, or even any part of the same file. That’s more of a guideline than a rule, but if you follow it, you will never have a merge conflict.
As we’ve seen, it’s not the end of the world if there is a merge conflict, but life sure is easier if they’re just avoided.
Takeaway: Without good communication and a good distribution of work on your team, you’re doomed. Make a plan where no one is stepping on toes, and stick to it.
This is really easy. Everyone has push access to the repo and does all their work on the main
branch.
Benefits:
Drawbacks:
Initial setup:
Workflow:
main
and resolves any merge conflicts.main
.In real life, this approach is probably only used on very small teams, e.g. three people at most, with frequent and easy communication between all members. If you’re working on a small team in school, it could very well be enough, but I’d still recommend trying a different approach just for the experience.
The other approaches are not that much more complex, and give you a lot more flexibility.
In this scenario, we treat main
as the working code, and we treat contributors’ branches as where work is done. When a contributor gets their code working, they merge it back into main
.
Benefits:
main
.Drawbacks:
main
, merging might become painful.main
with a lot of tiny commits.Initial setup:
Workflow:
main
into their branch; do a pull to make sure you have it. (The collaborator might already have the latest main
if no one else has merged into it, which will cause Git to say there’s nothing to do. This is fine.)main
.main
while you were testing, Git will complain that you have to pull before you can push. If there’s a conflict at this point, you’ll have to resolve, test, and push it. And you’ll have to merge main
back into your branch so that your branch is up-to-date.The result will look something like Figure 14.1 to start, where all the collaborators have made their own branches off of main
.
Let’s say Chris (on branch chris
) finishes up their work and wants other contributors to be able to see it. It’s time to merge into main
, as we graphically see in Figure 14.2.
After that, other contributors looking at main
will see the changes.
In this scenario, we treat main
as the published code that we’re going to distribute, often tagged with a release version number, and we treat a dev
branch as the working, unreleased code. And, as in the previous scenario, everyone has their own branches they’re developing on.
The idea is basically we’re going to have two versions of the working code:
main
.dev
.And then, of course, we’ll have one branch per collaborator.
Another way of thinking about it is that we’re going to have our internal build on dev
that is good for testing and then, when it’s all ready, we’ll “bless” it and merge it into main
.
So there will be a lot of merges into dev
from all the developer branches, and then every so often there will be a merge from dev
into main
.
The developers will never directly merge into main
! Usually that is performed by someone in a managerial role.
Overall the process works as in Figure 14.3. This is a busy image, but notice how Bob and Alice are only merging their work into the dev
branch, and then every so often, their manager merges the dev
branch into main
and tags that commit with a release number. (More on tagging later.)
Benefits:
Drawbacks:
dev
, merging might become painful.dev
with a lot of tiny commits.Initial setup:
dev
branch.Workflow:
dev
into their branch; do a pull to make sure you have it. (The collaborator might already have the latest dev
if no one else has merged into it, which will cause Git to say there’s nothing to do. This is fine.)dev
.dev
while you were testing, Git will complain that you have to pull before you can push. If there’s a conflict at this point, you’ll have to resolve, test, and push it. And you’ll have to merge dev
back into your branch so that your branch is up-to-date.Managerial Workflow:
dev
tested out and ready.dev
into main
.main
commit with some version number, optionally.