Work with Teams in GitHub
Learning Objectives
After completing this unit, you’ll be able to:
- Translate the GitHub workflow to an effective branching strategy for teams.
- Resolve merge conflicts on GitHub.
- Create atomic commits that represent a single unit of work.
Branching Strategies That Work
Now that you’ve gone through a simple GitHub flow example on your own, imagine how the workflow will work with a team. Multiply all of the branches, commits, and pull requests by the number of colleagues on your team and by active development. Many teams have done this before, and there are patterns that show success over time.
In general, branches should be short lived, created to accomplish a function, and deleted once they're merged. Short-lived branches prevent confusion, encourage up-to-date code, and set up developers for iterative improvements to projects.
Long-running branches can create problems if not used intentionally. Sometimes a long-lived branch make sense for a development branch, or for other situations when you need multiple levels of deployment-level code. Most of the challenges with long-running branches come from developers not having the most up-to-date version of each branch, creating needless merge conflicts, confusion, and work. While more complex branching workflows might seem like the right solution, they’re frequently over-complicated and the simpler GitHub flow works more effectively.
Some questions to ask your team about branching:
- Which branching strategy will we use?
- Which branch will serve as our main or deployed code?
- Will we use naming conventions for our branches?
- How will we use labels and assignees?
- Will we use milestones?
- Will we use Project Boards (Projects)?
- Will we have required templates/elements for Issues or pull requests (for example, shipping checklists)?
- How will we indicate sign-off on pull requests?
- Who will merge pull requests?
Remember, the power of branching comes from a safe place to make changes, and the power to review and test in pull requests. When you decide your branching expectations as a team, keep it lightweight and easy to learn. Focus on collaboration.
Handle Merge Conflicts
When you work with a team (and even sometimes when you work alone) you’ll occasionally create merge conflicts. At first, merge conflicts can be intimidating, but resolving them is actually quite easy.
Let’s try to create a merge conflict, and see what happens.
Create Multiple Branches with Conflicting Commits
We know that merge conflicts come about when there are multiple commits on separate branches to the same sections of the same files. So, to practice resolving one, let’s set up a conflict.
- From main, create a new branch (new-branch-1), make changes to the README.md file, and create a pull request:
- Enter command:
git checkout -b new-branch-1
- Make changes to the README.md file in your repository. Make a note of which lines you change.
- On new-branch-1, add and commit the changes:
- Enter command:
git add README.md
- Enter command:
git commit -m "Changes to the README"
- Enter command:
- Enter command:
- Push the branch to the remote repository:
git push -u origin new-branch-1
- Open GitHub and create a pull request for this commit
- Now, to create the next branch and pull request, check back out to main:
git checkout main
- Create a new branch (new-branch-2), make changes to the same file and create a pull request:
- Enter command:
git checkout -b new-branch-2
- Make a change to the README.md file to the same line of the file.
- Enter command:
git add README.md
- Enter command:
git commit -m “More changes to the README”
- Enter command:
git push -u origin new-branch-2
- In GitHub, create a pull request
- Enter command:
Merge One Pull Request
So far, there’s no merge conflict showing in either branch. In GitHub, merge your first pull request (from new-branch-1).
Resolve the Conflict on the Other Branch
After merging the new-branch-1 pull request, go to the pull request from new-branch-2.
You’ll see there is a merge conflict! Don’t panic, you can get through this. Depending on how complex the merge conflict is, you may be able to choose to resolve the conflict in the browser on GitHub, or you may need to resolve it locally.
To resolve it locally, you’ll merge main into your branch, and resolve the conflicts before completing the merge.
- Checkout to the branch that has a conflict:
git checkout new-branch-2
- Make sure your local repository is up to date:
git pull
- Merge main into the feature branch:
git merge origin/main
Notice you are merging the remote tracking branch and not your local copy of main—this is because the pull command updated the remote branches and the one you are on, but did not update main. - When you see there’s a conflict, that’s OK! Type
git status
to verify which file has the conflict. The files that have conflicts are listed underUnmerged Paths
. - Open that file in your text editor, and look for the merge conflict markers. (
<<<<<<<
,=======
,>>>>>>>
) - Both branches’ versions of code are present—pick which code you want to keep and delete the other. Be sure to delete the merge conflict markers created by Git and save your changes.
- Add and commit the saved changes to resolve the merge conflict:
- Enter command:
git add README.md
- Enter command:
git commit -m “Commit to resolve merge conflict”
- Enter command:
- Push the feature branch up to the remote:
git push
- Go back to the pull request on GitHub. The pull request is now free of conflicts.
- Merge the pull request.
Now that we’re done with these branches, delete them in GitHub, then use the git checkout main
and git pull
commands to sync your local repository.
Craft Atomic Commits
Crafting atomic commits is an important part of creating a readable and informative history of the project.
In a perfect world, you would never need to look at or change anything in your history. However, we don’t live in a perfect world, so version control lets us look into our change history if necessary. Each commit should be a small, logical unit of change and tell the story of your repository.
Let’s practice a command to help craft atomic commits, git add --patch
, or git add -p
for short. This command lets you add different parts of a file to the staging area, helping you make commits that are truly logical units of change.
- Download bigFile.md to your computer (you may need to right-click and choose Save Target As).
- In GitHub, upload bigFile.md to the main branch in your best-repo-ever repository:
- Click Upload files
- Choose the bigFile.md from your computer.
- Chose Commit directly to the main branch
- Click Commit changes
- Ensure your local main repository is up to date:
- Enter command:
git checkout main
- Enter command:
git pull
- Enter command:
- See what git is tracking:
git status
You should see that there is nothing to commit. - Make changes to the bigFile.md on lines 1 and line 100. (It doesn’t matter what the changes are.)
- Move some parts of some files to the staging area with the --patch flag:
git add -p
- Press
y
to stage your hunks, which is git language to your unit of change.
Wondering what all of those other options are for the hunks? Use the ?
to see a list of options above the hunk.