In the past, I’ve only used github for personal projects, so I didn’t have to deal with collaborating with other folks. Now that I’m working on an open-source project, I’m starting to get more familiar with all the cool features of git and github. So here’s the scenario:
- Project A is on github (aka the original repo).
- Alice has forked Project A on github and created a branch(/patch) off of that fork. (As a side note, the branch was already sent as a pull request to the original repo, but it hasn’t been merged yet.)
- I have to work on a new feature that is based off of Alice’s branch. So should I fork off of Alice’s repo or the original repo?
I decided on the latter option. Why? Because I’d like to make sure I keep up-to-date with the original repo, in case there are changes there that aren’t being pulled by Alice in her copy of the repo. So here’s how I set things up:
- Went on github and forked Project A so that I had my own personal copy of the original repo.
- Cloned my copy of the repo onto my machine. By default, cloning creates a remote called
originthat points to my copy of Project A on github.
git clone https://github.com/kpytang/[project-name.git]
- To make sure I keep tabs on the original repo, I add a remote called
upstreampointing to the original Project A on github.
cd [project-name] git remote add upstream https://github.com/[project-github-username]/[project-name].git
- Before pulling in Alice’s changes, I wanted to make sure my master branch remained as clean as possible, so I created a new branch for the feature I’m working on, and pulled Alice’s repo into that branch. To make sure things semantically made sense, I gave the branch a generic name based on the feature I’m responsible for (instead of the specific feature, which I’ll use later).
git branch [generic-feature-name] # creates a new branch git checkout [generic-feature-name] # makes it the active branch
Alternatively, the shortcut below does the same thing:
git checkout -b [generic-feature-name]
- Added Alice’s repo as a remote off of the newly created branch. I needed to add her entire repo before I could get to the one branch that I really wanted.
git remote add [alice] https://github.com/[alice]/[alice-project-name].git
- Grabbed Alice’s repo and merged that into my branch (off of the master branch, which is a clean copy of the original project).
git fetch [alice] git merge [alice]/master
- Grabbed Alice’s branch and merged that into the same branch
git merge [alice]/[branch-name]
- Created a new branch for the specific feature I’m working on. This way when I go to create another feature that’s also based Alice’s branch, I have an easy starting point to work off of.
git branch [specific-feature-name] git checkout [specific-feature-name]
Now I can start working and doing local commits of the new [specific-feature-name] branch and then when I’m ready, I can push my local commits to github. From there I can do a pull request to Alice’s branch and she can see what changes I’ve done. Alternatively, I can also do a pull request to the original repo as well. By separately out the two repos (Alice and the original repo), we can also easily do merges from one or both of those remote repos. Other tips:
- To pull changes from the original repo later on, make sure you’re on the right branch (i.e., the master branch) and pull in upstream changes from the original repo.
git checkout master # makes "master" the active branch git fetch upstream # grabs commits from the original repo git merge upstream/master # merges commit from original repo with the master branch
- To merge changes from one branch to another:
git checkout master # makes "master" the active branch git merge [branch] # merges commits from "branch" to the master branch
- To get a list of all your branches:
- To delete a branch:
git branch -d [branch] # deletes the "branch" branch locally git push origin :[branch] # deletes the "branch" branch on github (note the ':')
- Push changes to your own github repo doesn’t change:
git checkout master # makes "master" the active branch git push origin master # push commits from master branch to your copy of the repo on github
- Merging a pull request locally (useful for when you want to test things out first or when you don’t have push permissions for a repo):
git checkout master # makes "master" the active branch git pull https://github.com/[other-user]/repo.git [branchname]
Now you can work on the pull request, make local commits, etc. When you’re happy with the merged fix, you can push it back to your own repo:
git push origin master # push commits from master branch to your copy of the repo on github