Overview
Teaching: 20 min
Exercises: 40 minQuestionsObjectives
- How can we collaborate with people who we might not know yet?
- What is a fork?
- What is a pull request or merge request?
- What is code review?
- How do teams collaborate on GitHub or GitLab or Bitbucket?
- Get a mental representation of what is happening on GitHub.
- Get comfortable with the forking workflow.
In the forking layout, again we call one repository the “central” repository but people push to forks (their own copies of the repository on GitHub/GitLab/Bitbucket).
Features:
Real life examples:
origin
. The origin
is just an alias.$ git remote add upstream https://github.com/project/project.git
$ git remote rm upstream
$ git remote add group-repo https://example.com/exciting-project.git
$ git remote rm group-repo
$ git remote add upstream https://github.com/project/project.git
$ git remote add downstream https://github.com/userX/project.git
We synchronize remotes via the local clone.
To see all remotes:
$ git remote --verbose
For this exercise we will fork a different repository compared to earlier today. Please step out of the repository and check that you fork the forking-workflow-exercise.
Exercise: practice collaborative forking workflow
As an example we will collaboratively develop a cookbook for taco recipes, inspired by tacofancy.
Objectives:
- Learn how to fork, modify the fork, and file a pull request towards the forked repo.
- Learn how to update your fork with upstream changes.
Exercise:
- Helper prepares an exercise repository (see below; this will take 5-10 minutes).
- The exercise group works on steps A-E (15-20 minutes).
- There are two optional steps after step E for those who want more steps.
- After step E you can return to the main room. Please ask questions.
- We do step F and G together (instructor demonstrates, and everybody follows along in their repositories).
- If there is a lot of time left, step G can be done back in an exercise room.
Exercise preparation
Helpers in breakout-rooms:
- Create an exercise repository by generating from a template using this template: https://github.com/coderefinery/template-forking-workflow-exercise called
forking-workflow-exercise
- In this case we do not add collaborators to the repository (this is the point of this example).
- Share the link to the newly created repository in the shared document with your group.
Learners in breakout-rooms: Fork the helper’s newly created repository and clone the fork.
Instructor: Prepare an exercise repository for participants following via stream (see below).
Learners following via stream: Fork this repository into your namespace and then clone the fork to your computer.
Here is a pictorial representation of this part:
This is how it looks after we fork:
central:
fork:
After we clone the fork we have three in principle independent repositories:
central:
fork:
local:
Before we start any coding, open a new “Issue” on the central repository as a “proposal” where you describe your idea for a recipe with the possibility to collect feedback from others. After creating this issue note the issue number. We will later refer to this issue number.
Discuss with your neighbor why it can be useful to open an issue before starting the actual coding.
Before we do any modification, we create a new branch and switch to it: this is a good reflex and a good practice. Choose a branch name which is descriptive of its content.
On the new branch create a new file which will hold your recipe,
for instance traditional_coderefinery_tacos.md
(but change the name so that we will have different recipes in the repo). You can get inspired
here. Hopefully we all use different
file names, otherwise we will experience conflicts later (which is also interesting!).
There is also a file called test.py
which will automatically verify whether your recipe contains the string
“taco” (case insensitive). This is there to slowly introduce us to automated testing.
Once you are happy with your recipe, commit the change and in your commit message reference the issue which you have opened earlier with “this is my commit message; closes #N” (use a more descriptive message and replace N by the actual issue number).
$ git branch yourname/somefeature
$ git checkout yourname/somefeature
$ git add <your taco recipe>.txt
$ git commit -m "<message>;closes #N"
And here is a picture of what just happened:
central:
fork:
local:
Now push your new branch to your fork. Your branch is probably called something else than “feature”. Also verify where “origin” points to.
$ git push origin yourname/feature
central:
fork:
local:
Then file a pull request from the branch on your fork towards the master branch on the repository where you forked from.
Here is a pictorial representation for parts D and E:
A pull-request means: “please review my changes and if you agree, merge them with a mouse-click”.
Once the pull-request is accepted, the change is merged:
central:
fork:
local:
Wait here until we integrate all pull requests into the central repo together on the big screen.
Observe how the issues automatically close after the pull requests are merged (provided the commit messages contain the right keywords).
(Optional) Exercise: try to send a conflicting pull request
If you complete parts A-E much earlier than others, try to send another pull request where you anticipate a conflict with your first pull request.
(Optional) Exercise: practice making changes to your pull request
You can do that by pushing new commits to the branch where you sent the pull request from. Observe how they end up added to your pull request.
We do this step together on the main screen (in the main room). The instructor shows a submitted pull request, discusses what features to look at, and how to discuss and review.
At the same time, helpers can review open pull requests from their exercises groups.
We do this part after the contributions from all participants have been integrated.
Once this is done, practice to update your forked repo with the upstream changes and verify that you got the files created by other participants.
Make sure that the contributions from other participants are not only on your local repository but really also end up in your fork.
Here is a pictorial representation of this part:
We will discuss two solutions:
$ git remote add upstream https://github.com/coderefinery/forking-workflow-exercise.git
$ git fetch upstream
$ git branch -va
central:
fork:
local:
$ git checkout master
$ git merge upstream/master
$ git branch -va
central:
fork:
local:
$ git push origin master
$ git branch -va
central:
fork:
local:
Remotes are aliases. We can use remote URLs directly.
Here we pull from the central repo and push to our fork (replace with the repository you forked if needed):
$ git checkout master
$ git pull https://github.com/coderefinery/forking-workflow-exercise.git master
$ git push https://github.com/user/forking-workflow-exercise.git master
(from Star Wars Episode IV - A New Hope)
Discussion: Always create a feature branch
- Never commit to the branch you wish to submit the pull request towards.
- For each pull request create a new branch.
Motivation:
- Limits the risk that commits get accidentally appended to an open pull request.
- History-rewrite (rebased and/or squashed commits) on the central repository does not lead to a diverging local default branch.
See also this blogpost for an explanation.
Key Points
Working with multiple remotes is not as scary as it looks.
origin
is just an alias.We can add and remove remotes.
We can call these aliases as we like.
We synchronize remotes via the local clone.
To see all remotes use
git remote -v
.If you are more than one person contributing to a project, implement code review.