Git for dummies
Overview of Using git in OpenEMR
The goal of these instructions are to get you started using git in OpenEMR as quickly as possible. Once you master the below information, then should be easy to at least code and get code reviewed and get code committed.
Video Tutorial
- Here is a very nice video/tutorial by Ken at MI-Squared that is based on the instructions below. If have the time, suggest watching it first.
Step 1: You too can have your very own public openemr repository on github.com!
- 1. Sign up for an account on github.com
- 2. Make a key using the instructions at: http://help.github.com/msysgit-key-setup/, and put it in your gihthub.com account
- 3. Make a fork from the main openemr github repository at: http://github.com/openemr/openemr
Step 2: Now, set up your local repository
- 1. Install a git client on your local computer.
- * Make sure your install is configured to handle CRLF line ending conversion: See: http://help.github.com/dealing-with-lineendings/
- 2. Clone your github repository:
git clone git@github.com:yourGithubUserName/openemr.git openemr
- (now your github repository is called 'origin')
- 3. Move into your newly created openemr respository:
cd openemr
- 4. Set up a connection to the main openemr github respository:
git remote add upstream git@github.com/openemr/openemr.git
- (now the main openemr github repository is called 'upstream')
- 5. All the pieces are now set up. You have your local repository that is connected to your public github repository(origin) and is connected to the official openemr github repository(upstream)
Step 3: Feeding your repository
- 1. The 'master' and 'rel-*' are sacred branches that should not be modified by mere mortals. Never ever manually modify these branches on your local or public github repository. These can only be fed by the official openemr github repository.
- 2. First, feed your local repository(from upstream):
git checkout master git pull upstream master
- (Now your local repository 'master' sacred branch is fed by most current official OpenEMR code)
- 3. Second, feed your github repository:
git push origin master
- (This command will feed your public github repository with updated code from your local repository; note there is no need to mention specific branches)
- 4. That's it. You now have the most current codebase in your local and public github repository. I recommend repeating these steps frequently to keep your repositories well feed.
Tenet 1: Branches are Supreme
- You may ask: If I can't work in the master or rel-320 branches, then where do I work in. The answer is, you make new branches and put your work in there. Make a branch for every new project, bug fix, etc. To make a branch off of 'master' and go into it do the following:
git checkout master git checkout -b newbranchname
- Then do your work in this branch for your project. Recommend committing often via:
git commit -a
- Or if you want to amend your previous commit (i.e. you are "fixing" it, it's not yet published and don't want to clutter the commit log with a new entry):
git commit --amend -a
- You can upload your branch to your public github repository via:
git push origin newbranchname
- (Now others can review and test your code)
Tenet 2: My custom branch and code is now out of date... time for rebase...
- What happens to my custom branches as the master and rel-320 continue to get updated (via step 3 above)? Your patches and branches get out of date!!
- This can be dealt by doing the following):
- 1. rebase your outdated branch (I am assuming that the workbranchname was originally branched off master):
git checkout workbranchname git rebase master
- 2. replace your outdated branch from your public git repository(origin)(yes, the plus-sign is supposed to be there):
git push origin +workbranchname
Submit your code for review
- Now you've done some coding on a custom branch and want to submit it for review (with the goal of getting it included in the main OpenEMR codebase).
- No code is too small (ie. a quick bug patch) or too big; please do not feel the need to submit "perfect" code. We are just glad to get any contributions, and we will gladly provide a friendly review of your code.
- It is best to do this from the repository that you created in the above tutorial and ensure you are following the steps and tenets above! This means all work is done in custom branches, and that you have not manually touched the 'master' or 'rel-320' branches, which are only updated from the official github mirror repository at 'upstream'.
- The steps involve updating your local openemr repository, updating your custom branch, and then notifying the OpenEMR developers to review your code.
- 1. Update your local repository:
git checkout master git pull upstream master
- 2. Update your custom branch (fix any conflicts that arise during the rebase before proceeding):
git checkout <your_branch> git rebase master
- 3. Publish your custom branch to your public github repository:
If this is the first time you are publishing this branch:
git push origin <your_branch>
If you have already published this branch previously, then can refresh it with the following command (note the plus sign before your custom branch name):
git push origin +<your_branch>
- 4. Submit your code as a Pull Request on github: https://github.com/openemr/openemr/pulls
Try out somebody else's code
- It is best to do this from the repository that you created in the above tutorial and ensure you are following the steps and tenets above! This means all work is done in custom branches, and that you have not manually touched the 'master' or 'rel-320' branches, which are only updated from the official github mirror repository at 'upstream'.
- The steps involve creating a pointer to somebody else's repository, fetching their repository information, and then collecting the desired code from them.
- 1. Create a pointer to the other user's repository:
git remote add <user_repo_name> <actual repository address>
- (for example to create a pointer to brady's repository, do the following 'git remote add brady git://github.com/bradymiller/openemr.git')
- 2. Fetch the information from the other user's repository:
git fetch <user_repo_name>
- (for example to fetch info from brady's repository, do the following 'git fetch brady')
- 3. Create a branch that you will put the other user's code into:
git checkout master git checkout -b test_branch
- 4. 'pull' or 'cherry-pick' the other user's code into your repository (into your test_branch). The decision to use 'pull' or 'cherry-pick' depends on how much you trust the other user. If the other user is updating their repository frequently and correctly then 'pull' will suffice, however the safest route to go is the 'cherry-pick' method especially if planning to commit this code to the sourceforge repository.:
If use 'pull':
git pull <user_repo_name> <user_branch_name>
- (for example to pull a branch of code from brady's repository, do the following 'git pull brady <branch_from_brady_repo>')
If use 'cherry-pick': (SHA numbers of other user's commits can be found in the log of their branch(for example 'git log brady/<branch_from_brady_repo>'). Remember to cherry-pick them in the order they were created.)
git cherry-pick <sha# of first commit> git cherry-pick <sha# of second commit, if there is a second commit> etc.
Putting that OpenEMR code to work
- Now you want to test the branch that is currently checked out. I recommend never running OpenEMR directly from your git repository. Instead, it is best to copy the current checked out git copy to your web server directory and test it there. I have posted two scripts below that will do this automatically for you (hopefully a windows scripting guru will post a windows script soon).
Tips and Tricks and Tools that are useful
The following is collection of ways to use git commands, helpful aliases and utilities that you may find to be of assistance. Some of these rely on Unix commands. If you are using windows I suggest installing cygwin or a similar GNU Utilities suite.
- Here is a OpenEMR sourceforge forum thread that discusses git tips and trick: GIT tips and tricks
- How to find out what changed since a certain date
git whatchanged --since=MM-DD-YYY (or --since=yesterday, etc)
- How to filter that list (in Linux command line) to produce just a list of files for copying to running install or similar
git whatchanged --since=yesterday | grep "\.\.\. " | awk '{print $6}'
- Some useful linux aliases that help prevent doing something on the wrong branch
alias pullupstream='git checkout master; echo Continue\?;read X;git pull upstream master' alias pullorigin='git checkout master; echo Continue\?;read X;git pull origin master' alias pushorigin='git checkout master; echo Continue\?;read X;git push origin master'
- Some useful status reporting formats
alias gitgraph='git log --graph --abbrev-commit --pretty=oneline --decorate' alias gitlog='git log --name-only' alias gstat='git branch -v | grep \* ;git status -s' (show the branch name and the short status) alias diffnames='git diff --name-only master' (list the files that differ from the master branch)
- How to tell which of your branches have been rebased (or contain) the lastest commits from the master branch
git branch --contains=`git branch -v | grep '* master' | awk '{print $3}'`
- How to not see whitespace changes when looking at commit diffs on github
- Add a ?w=1 to the end of the web address.
- For example:
- http://github.com/openemr/openemr/commit/f6d1333ad39cba0c578892a8c425d83f2b3f2286 (shows changes in whitespace)
- http://github.com/openemr/openemr/commit/f6d1333ad39cba0c578892a8c425d83f2b3f2286?w=1 (does NOT show changes in whitespace)
- For example:
- Add a ?w=1 to the end of the web address.
- Utilities
- qgit - an excellent graphical repository explorer, kind of a local github view mode
- gitg - another way to look at the repository graphically with clear branching indicators
More information
- A very nice article describing the 'merge' and 'rebase' commands: Merge vs Rebase: A Deep Dive into the Mysteries of Revision Control.
- Check out Stephens documentation of git
- Here are links on delicious I compiled while learning how to use git
- Brady's tip for cleaning a local branch: https://github.com/openemr/openemr/pull/657#issuecomment-295630669
- And there's always google
Advanced Usage
Submit your code for commit (For Privileged Developers)
- Now you've done some coding on a custom branch and want to submit it for commit to the OpenEMR codebase. Note this is a method for Privileged Developers to fast-track their commit into the sourceforge OpenEMR repository. If you want your code reviewed or you aren't a Privileged Developer then follow the instructions located above instead.
- It is best to do this from the repository that you created in the above tutorial and ensure you are following the steps and tenets above! This means all work is done in custom branches, and that you have not manually touched the 'master' or 'rel-320' branches, which are only updated from the official github mirror repository at 'upstream'.
- The steps involve updating your local openemr repository, updating your custom branch, and then notifying an OpenEMR Integration Developer to commit your code.
- 1. Update your local repository:
git checkout master git pull upstream master
- 2. Update your custom branch (fix any conflicts that arise during the rebase before proceeding):
git checkout <your_branch> git rebase master
- 3. Publish your custom branch to your public github repository:
If this is the first time you are publishing this branch:
git push origin <your_branch>
If you have already published this branch previously, then can refresh it with the following command (note the plus sign before your custom branch name):
git push origin +<your_branch>
- 4. Let the Integration Developers know to commit your code by posting a message in the sourceforge OpenEMR developer forum (simply provide a link to your published github branch, and it will be committed within 24 hours).
Committing to the official git repository on GitHub (merge method) (For Integration Developers)
- This is for Integration Developers whom have commit access to the GitHub git repository.
- It is best to do it from the repository that you created in the above tutorial and ensure you are following the steps and tenets above! This means all work is done in custom branches, and that you have not manually touched the 'master' or 'rel-320' branches, which are only updated from the official GitHub repository at 'GitHub' (official github mirror repository at 'upstream').
- We are assuming that your 'upstream' remote is directed to the openemr repository on GitHub.
- Then when you have a custom branch on your local repository ready to commit to the GitHub git repository, do the following:
- 1. This step is extremely important to ensure your local repository is compatible with the GitHub repository (otherwise you risk breaking the official GitHub repository). The following commands will fetch the GitHub commit information and then ensure you have no local incompatible commits. If the 'git rev-list' command produces any output that means something is wrong, and you need to get help from the sourceforge developer forum to fix your repository before proceeding!!!!:
git fetch upstream git rev-list master --not upstream/master
- 2. Checkout your local 'master' branch:
git checkout master
- 3. Pull the most recent code from the sourceforge 'master' branch:
git pull upstream master
- 4. Rebase your custom branch (fix any conflicts that arise during the rebase before proceeding).
git checkout <your_branch> git rebase master
- 5. Merge your custom branch into your master branch.:
git checkout master git merge <your_branch>
- 6. Now need to do two sanity checks to ensure you do not break the main repository before you perform the commit operation. First, look at the log and ensure that the applicable number of commits are happening and nothing looks funny (if any oddities/confusion/questions, then post this log in the sourceforge forums before proceeding). Second, run the below 'git rev-list' command; the number of commits you plan to push should equal the number of lines of output you get with this command (if this is not the case, then you need to get help from the sourceforge developer forum to fix your repository before proceeding!!!!)
git log git rev-list master --not upstream/master
- 7. Commit it to the official GitHub git repository:
git push upstream master
Committing to the official git repository on GitHub via GitHub GUI (For Integration Developers)
- Only use if the PR is rebased to most recent code base and there are no merge commits in the PR.
- Use the Squash and Merge button when bringing in a PR.
- The command line methods (when need to have more control) are detailed below.
Committing to the official git repository on GitHub (cherry-pick method) (For Integration Developers)
- This is for Integration Developers whom have commit access to the GitHub git repository.
- It is best to do it from the repository that you created in the above tutorial and ensure you are following the steps and tenets above! This means all work is done in custom branches, and that you have not manually touched the 'master' or 'rel-320' branches, which are only updated from the official GitHub repository at 'GitHub' (official github mirror repository at 'upstream').
- We are assuming that you are using 'upstream' remote for the openemr repository on github.
- Then when you have a custom branch on your local repository ready to commit to the GitHub git repository, do the following:
- 1. This step is extremely important to ensure your local repository is compatible with the GitHub repository (otherwise you risk breaking the official GitHub repository). The following commands will fetch the GitHub commit information and then ensure you have no local incompatible commits. If the 'git rev-list' command produces any output that means something is wrong, and you need to get help from the Sourceforge developer forum to fix your repository before proceeding!!!!:
git fetch upstream git rev-list master --not upstream/master
- 2. Checkout your local 'master' branch:
git checkout master
- 3. Pull the most recent code from the GitHub 'master' branch:
git pull upstream master
- 4. Rebase your custom branch (fix any conflicts that arise during the rebase before proceeding).
git checkout <your_branch> git rebase master
- 5. Cherry-pick each of your commits from your custom branch into your master branch. SHA numbers of your commits can be found in the log of your custom branch('git log <your_branch>'). Remember to cherry-pick them in the order they were created.:
git checkout master git cherry-pick <sha# of first commit> git cherry-pick <sha# of second commit if there is a second commit> etc.
- 6. Now need to do two sanity checks to ensure you do not break the main repository before you perform the commit operation. First, look at the log and ensure that the applicable number of commits are happening and nothing looks funny (if any oddities/confusion/questions, then post this log in the sourceforge forums before proceeding). Second, run the below 'git rev-list' command; the number of commits you plan to push should equal the number of lines of output you get with this command (if this is not the case, then you need to get help from the sourceforge developer forum to fix your repository before proceeding!!!!)
git log git rev-list master --not upstream/master
- 7. Commit it to the official GitHub git repository:
git push upstream master
Committing other user's code to the official git repository on GitHub (quick and safe method) (For Integration Developers)
- This is for Integration Developers whom have commit access to the GitHub git repository, and is the quickest way to commit somebody else's code. This means the other user needs to provide a a branch with their code that is rebased to the most recent official 'master' branch on GitHub.
- It is best to do it from the repository that you created in the above tutorial and ensure you are following the steps and tenets above! This means all work is done in custom branches, and that you have not manually touched the 'master' or 'rel-320' branches, which are only updated from the official GitHub repository at 'GitHub' (official github mirror repository at 'upstream').
- 1. Create a pointer to the other user's repository (if you do not already have a pointer for the other user's repository):
git remote add <user_repo_name> <actual repository address>
- (for example to create a pointer to brady's repository, do the following 'git remote add brady git://github.com/bradymiller/openemr.git')
- 2. This step assumes 'upstream' is your remote for the openemr repo on GitHub. is extremely important to ensure your local repository is compatible with the GitHub repository (otherwise you risk breaking the official GitHub repository). The following commands will fetch the GitHub commit information and then ensure you have no local incompatible commits. If the 'git rev-list' command produces any output that means something is wrong, and you need to get help from the sourceforge developer forum to fix your repository before proceeding!!!!:
git fetch upstream git rev-list master --not upstream/master
- 3. Checkout your local 'master' branch and update it from the GitHub repository:
git checkout master git pull upstream master
- 4. Fetch the information from the other user's repository:
git fetch <user_repo_name>
- (for example to fetch info from brady's repository, do the following 'git fetch brady')
- 5. 'cherry-pick' the other user's code into your 'master' branch. (SHA numbers of other user's commits can be found in the log of their branch(for example 'git log brady/<branch_from_brady_repo>'). Remember to cherry-pick them in the order they were created.) If the cherry-pick's do not work (ie. there are conflicts) then terminate the merge and ask the other developer to produce a rebased branch, and then try again:
git cherry-pick <sha# of first commit> git cherry-pick <sha# of second commit, if there is a second commit> etc.
- 6. Now need to do two sanity checks to ensure you do not break the main repository before you perform the commit operation. First, look at the log and ensure that the applicable number of commits are happening and nothing looks funny (if any oddities/confusion/questions, then post this log in the sourceforge forums before proceeding). Second, run the below 'git rev-list' command; the number of commits you plan to push should equal the number of lines of output you get with this command (if this is not the case, then you need to get help from the sourceforge developer forum to fix your repository before proceeding!!!!)
git log git rev-list master --not upstream/master
- 7. Commit it to the official GitHub git repository:
git push upstream master