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 main.
git checkout main
-
Let's make sure our local main is up to date with the upstream main.
git pull upstream main --ff-only
-
Assuming the pull was successful make a new branch based on main 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_uw
git push
will also work if you did the-u
in 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
main
branch of theupstream
repo has diverged from your local branch. You need to mergemain
into your branch and manually fix the conflicts. You might be lucky and, on your branch, this command works:git fetch upstream main git merge upstream/main
The 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
git
commands, you can always dogit rebase --abort
to abort the process and revert to the status before starting the merge.The merge with conflict resolution processis much easier with
PyCharm
, for situations with serious conflicts, you can reference to Step 7: Conflicts 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_uw
You can delete the branch on your fork at
github
website. 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
git branch --merged # list all the branches whose commits are fully merged and can therefore be deleted without worry
- 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,
remote
means the repository ongithub
. With aremote
setup, 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 repository
can be obtained as we did in theclone
section andremote name
can be any name that is meaningful (easy to remember) to you. -
To view which remotes your local repository is synced to:
git remote -v
And you might see something similar to this
-
By default
origin
is always set to the repository you cloned. You can rename anyremote
by 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 remote
These 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 main is synced with the upstream main (VERY IMPORTANT...can avoid lots of headaches later). You can update your local
main
by:git merge --ff-only upstream production #update your local main
-
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 main. Always make a branch and edit that. Later you will merge it back into main.
-
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 status
Here you see we have
Untracked files
andChanges not staged for commit
. The difference between them is as following. -
Git
is 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 status
will 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
commit
the changes. To commit your edits.git commit # this will open the core editor currently used by git git commit -m "<commit message>"
Usually
git commit
will 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 diff
to 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\main
.
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\main
.
For this situation, the step you need is to merge upstream into your local branch,
manually resolving the conflicts. 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 conflict
resolution 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 merge to. If not,
git checkout <branch name>
-
Make sure you have all the upstream updates on your local computer
git fetch upstream main
-
Make active (by clicking on it) an open file that is on your active branch as in the following figure.
In this case
institutions.yml
is active -
checkout the branch in your terminal
-
type
git pull upstream main
-
Click on your
PyCharm
window and open the file that has conflicts -
PyCharm
should detect that there are conflicts and offer you the chance to resolve the conflicts. Accept and it will open a window that allows you to select things from main and also from your local. -
As a general rule, make sure the accept everything from main as those are things that have been reviewed and merged.
-
Accept anything from local that is not conflicted
-
Resolve conflicts as best as you can by making good decisions. If you are not sure reach out and ask Simon or another experienced person. It is much easier to discuss and resolve things correctly at this point than fixing bugs introduce by bad merges later.
-
As an exapmle, here are some screenshots. A handy window pops up that has my branch version on the left, the upstream/main 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
PyCharm
accepts 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
PyCharm
does 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/main
edit 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. -
PyCharm
continues the merge, looking for the next conflicted commit and all the steps above are repeated, until we get through all the commits. ThenPyCharm
saysmerge successful
. -
You are all done! Well done. But don’t forget to push your rebased branch to your fork to update the PR.
git push origin <branch name>
-
After your PR is pulled in, your hard works have been merged into
upstream
but your local copy hasn't been updated. So that is the reason why we want to keep localmain
branch clean - because we want to make it always aligned withupstream
. -
After your PR is merged, you can update your local
main
by:git checkout main #checkout to local main git merge --ff-only upstream production #update your local main
-
Now your local
main
branch is updated and if you want to work on other features, you can:git checkout -b <new branch name> #switch to a new branch
So your new branch would have latest code with
upstream
and 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.