This page summarizes the git workflow we use in the Billinge Group. It is not supposed to teach you how to use git. It is based on the numpy workflow. For more on git, GitHub and git workflows, please go to full git documentation. Also Google and stackoverflow is incredibly helpful.
Here is a brief example of the workflow we will cover. you can refer back to this later whenever you want. If this is your first time through, jump to Section Step 0 below where things are discussed in more detail.
-
Let's start our new branch on our existing master.
git checkout master -
Let's make sure our local master is up to date with the upstream master.
git pull upstream master --ff-only -
Assuming the pull was successful make a new branch based on master for our issue fix with memorable name.
git checkout -b add_huskies_to_uw -
Work work work, test test test, commit commit commit.
-
Create a new branch on our fork and push these commits there.
git push -u origin add_huskies_to_uw -
Go to fork on GitHub and create a PR into the main repo using the website.
-
Wait for comments, fix comments and commit.
-
Push comments to the same branch and they will automatically update the same PR
git push origin add_huskies_to_uwgit pushwill also work if you did the-uin the earlier push, which creates a permanent link between the local and fork branch. -
If you see that your PR has a conflict on the main page, it means that the
masterbranch of theupstreamrepo has diverged from your local branch. You need to "rebase your branch onto the upstream/master branch". You might be lucky and, on your branch, this command works:git fetch upstream master git rebase upstream/masterThe first step fetches any upstream changes to your local computer but doesn't apply them. If there is a serious conflict though things get more complicated. If the conflict is complicated and you are not sure if you can solve the conflict with pure
gitcommands, you can always dogit rebase --abortto abort the process and revert to the status before rebasing. The rebase process with conflict resolution is much easier withPyCharm, for situations with serious conflicts, you can reference to Step 7: Rebase section below. -
After your PR is pulled in. You can delete your local branch and stay nice and organized.
git branch -d add_huskies_to_uwYou can delete the branch on your fork at
githubwebsite. Congratulations! You completed your fix. You are now ready to fix your next issue.
Below is a code block for reference. It includes some of the most useful git commands you will use to complete the workflow introduced below. If it's your first time here, skip this block and finish reading the workflow below.
git remote add <name> <remote url> # add a remote
git remote -v # list all remotes
git remote update # update and sync with remote branches
git branch # list all local branches
git branch -a # list all available branches
git checkout <branch name> # check out an already existing branch. only check out local branches
git checkout -b <new branch name> # check out to new branch based on current branch
git add <filename> # add changes into working history
git commit -m "CODE: <my commit message> # commit changes
git push origin <branch_name> # push local branch to branch on your Fork
- First you need a github account.
- You would also need to have git installed on your computer.
- Read chapters 15 and 16 of Effective Computation in Physics by Scopatz and Huff (it is strongly recommended that you get a copy, but we do have).
- We also recommend PyCharm as an IDE/editor because
- It's powerful.
- It makes rebasing much easier.
- It's widely used in the group, so you can get help easily.
- As students you can request a free copy of the full production version!
Forking will allow you to make a pull-request (PR) later. We need it for our workflow, even if it may not be clear now why. fork can be done through github website:
-
Go to your fork on GitHub.
-
Click on the green clone or download button at the top-right corner:
-
The link shows here is the identity to this repository. Click on the "clipboard icon" to copy the link to your clipboard. You can then copy it and paste to your terminal and do:
git clone <url just copied>Now you have your local copy of your remote repository!
-
Navigate to your the directory you just cloned.
-
As suggested by the name,
remotemeans the repository ongithub. With aremotesetup, you are able to compare the difference, push edits to and pull changes with respect to remote(s). -
Your local repo is already connected to the Fork because you cloned it from the fork. However, you need to connect it to the "upstream" repo that the fork was forked from. To do this we need to "add a remote" using the following command:
git remote add <remote name> <url to the github repository>url to the github repositorycan be obtained as we did in theclonesection andremote namecan be any name that is meaningful (easy to remember) to you. -
To view which remotes your local repository is synced to:
git remote -vAnd you might see something similar to this
-
By default
originis always set to the repository you cloned. You can rename anyremoteby doing:git remote rename <old name> <new name> -
By convention, we usually name the remote repo of the parent repository of your fork as
upstream. -
If we want to get any changes from remote repositories onto our local computer, we can use the following commands:
git remote update #update all remotes git fetch <remote name> #update certain remoteThese won't affect our local branch but will make the remote changes available if we want to merge or compare.
Branches are like virtual environments. Each of them has its own working history that is
synced with certain remote. Once you checkout (switch) your branch, you
are literally jumping into another parallel world where files live in another history.
-
To list all available branches (including ones from all remotes):
git branch -a -
To checkout (switch) to any branch available branch:
git checkout <branch name> -
To create a new branch based on current branch:
git checkout -b <new branch name> -
Next, make sure your local master is synced with the upstream master (VERY IMPORTANT...can avoid lots of headaches later). You can update your local
masterby:git merge --ff-only upstream production #update your local master
-
Before your edits, checkout to a new branch. Since creating a branch is free on github, it's suggested to keep every branch as granular as possible.
-
It's also recommended never to edit your local master. Always make a branch and edit that. Later you will merge it back into master.
-
Start your edits with your favorite editor (we recommend
PyCharm). -
After your edits, commit them to your local git repo. To check current working history:
git statusHere you see we have
Untracked filesandChanges not staged for commit. The difference between them is as following. -
Gitis all about version control so while you are working you might edit existing files or you might create a new file, which hasn't been included into the working tree yet. The newly created file will be listed asUntracked files. -
If a file as been added into your working history before, then every time you change it,
git statuswill be listed asChanges not staged for commit. -
To add this files into your working history:
git add <path to files you want to add> git add --all # (or git add -A) add all edited files shows in git status -
After adding files into history, we want to
committhe changes. To commit your edits.git commit # this will open the core editor currently used by git git commit -m "<commit message>"Usually
git commitwill bring you to something similar to this screen shot:The first line is a brief of your commit. It shouldn't be more than a line. Starting from the third line, it is the main body of your commit message. You can be as detailed as you want.
-
It is important to make your commit message as clear as possible so that other contributor will be able to trace back.
-
You can also use
git diffto see detailed difference between current commit and the last commit. -
Then we are ready to push our hard work back to
remote. To push our local version to a specific branch in a given remote:git push <remote name> <branch name>
The final step is to get your changes incorporated into the parent (upstream)
repo. You can't just push them there because you could cause all kinds of
problems. Instead, you issue a pull request (PR).
pull request means you are requesting people to consider your edits and github
makes it very easy to compare edits.
-
PR makes it easy to compare difference and start discussions. To issue a PR through github web page:
-
After issuing a PR, other developers can view your edits, add comment and eventually decide whether to pull in your PR.
-
You can always update your PR by pushing new edits to the same branch under your fork.
Sometimes you may find Github shows This branch has conflicts that must be resolved in your PR page. This simply means the remote branch
this PR is based on is in a different working history as upstream\master.
Github provides a button in the PR page to solve the conflict,
but DO NOT use this approach since it creates an extra commit
and could further divert you away from upstream\master.
For this situation, the step you need is rebase. Rebasing can be
carried out on the command-line using git commands (described later) but
it is much easier using a python IDE with built-in rebasing tools, such
as our good friend PyCharm. Here we reproduce the steps to do the rebase
using PyCharm. It will be slightly different if you are using a
different IDE. Look lower down if you want to do it directly with Git.
-
Make sure that you are on the branch that you are actively working on and want to rebase. If not,
git checkout <branch name> -
Make sure you have all the upstream updates on your local computer
git fetch upstream master -
Make active (by clicking on it) an open file that is on your active branch as in the following figure.
In this case
institutions.ymlis active -
Left click on
Git: <branch name>in the lower right of thePyCharmwindow. -
A list of all the linked repositories and branches will pop up. If you click on any of them, it will give a list of possible actions regarding that branch. In the example in the Figure the branch checked out is
british_drug_cosand after clicking on that I selectedupstream/master. The options are tocheck-out,compare with,merge onto current,delete, and of interest hererebase current onto selected, which is what we want to do -
Select
rebase current onto selectedwhich will rebasebritish_drug_cosbranch onto the latest fetched version ofupstream/masterwhich is exactly what we want to do. -
PyCharmstarts the rebase by going and looking for all the commits from upstream that are missing on our branch. While it works, it tells us what it is doing in the center-bottom of the page. Here it is firststashing changes from rg-db-publicbecause I had made some changes that I hadn’t committed.PyCharmwill ask git to stash them, make all the rebasing updates, then restore them back into the directory at the end. I don’t have to do anything. -
Now
PyCharmfinds a commit in the commit chain that has a conflict with the edits on my branch, so a new window pops up with this information in it. I click merge. -
Now a handy window pops up that has my branch version on the left, the upstream/master version on the right, and the merged version in the middle. I want to accept all the changes that don’t raise conflicts. These appear in green, and I can accept them all by clicking on one of the icons with green arrows in the top tools panel. I click on the one that has green arrows from the left and right, and
PyCharmaccepts ALL these changes. -
Either I can then navigate to the next (the first in this case) conflict by clicking a down-arrow, or in this case
PyCharmdoes it automatically. Conflicts appear in red. -
This conflict is easy to resolve because the upstream change is a new item, so I want to accept it. I do that by clicking the
<<sign on the right. -
Now the conflicting edit in my version is just a carriage return on the end of the line. I could click
>>and it would also be accepted, and placed after the other one, or in this case it is probably better to click X to not accept it, since it seems that theupstream/masteredit already has a line-end in it. Great. If there were more conflicts to resolve I could navigate through them, but this was the last so a message pops up “all changes have been processed, save changes and finish merging”. I click on this to accept the changes, or I could click on Apply in the lower corner. -
PyCharmcontinues the rebase, looking for the next conflicted commit and all the steps above are repeated, until we get through all the commits. ThenPyCharmsaysrebase successful. -
You are all done! Well done. But don’t forget to push your rebased branch to your fork to update the PR. This may have to be a force-push (--force)
git push origin <branch name> --forcebecause you have changed the
gitcommit history. Be very careful when force pushing. In general you only ever do it to your fork, and you should only need it after a rebase.
-
After your PR is pulled in, your hard works have been merged into
upstreambut your local copy hasn't been updated. So that is the reason why we want to keep localmasterbranch clean - because we want to make it always aligned withupstream. -
After your PR is merged, you can update your local
masterby:git checkout master #checkout to local master git merge --ff-only upstream production #update your local master -
Now your local
masterbranch is updated and if you want to work on other features, you can:git checkout -b <new branch name> #switch to a new branchSo your new branch would have latest code with
upstreamand you can start previous steps :)
Up to now, we have cover the most common git work flow. Of course, you will find
minor difficulties during your work. Please be patient and follow the instruction
git gives at the run time.















