= Git = [[TOC]] Sahana Eden uses the Git DVCS & hosts active branches on [https://github.com GitHub] == Developer Workflow == === Fork a fresh repository === If you've not used !GitHub before: 1. Sign-up for an account on [https://github.com GitHub] 1. Set up git on you your computer by following [[http://help.github.com/set-up-git-redirect|these instructions]].[[BR]] Note: In order to contribute code back to the Eden project, you need to "push" your changes to !GitHub, and !GitHub requires you to authenticate for that. The instructions describe authenticating using a password. If you don't want to do do that, you can use SSH keys instead, but the [[https://help.github.com/articles/generating-ssh-keys|SSH setup]] is longer, and they do not provide instructions for Windows. If you're using Windows, you can follow [[https://help.launchpad.net/YourAccount/CreatingAnSSHKeyPair#Windows_.28PuTTY.29|these instructions]]. They're for Launchpad, not !GitHub. The only difference is, while you're doing Step 5 (which has you copy the "OpenSSH" formatted public key to the clipboard), go over to the !GitHub instructions, to the "Add your SSH key to !GitHub" section. Ignore the Linux commands and do the part that saves your public key in your !GitHub account. If you want, you can also save that public key in a file. 1. There is [[https://help.github.com/|on-line help at GitHub]] Then get your own copy of the Eden repository (repo) on both !GitHub and your local machine: 1. Fork the Eden repo at: https://github.com/flavour/eden/fork_select 1. Use git to clone your own new fork down to your PC, as follows: {{{ cd web2py/applications git clone git@github.com:mygitusername/eden.git cd eden git remote add upstream git://github.com/flavour/eden.git }}} [[Image(https://docs.google.com/drawings/pub?id=1TppJKr9Qrq6I2KpkljRixx5gYh1seRqCXk8KDWdeIF0&w=395&h=241)]] [[BR]] https://docs.google.com/drawings/d/1TppJKr9Qrq6I2KpkljRixx5gYh1seRqCXk8KDWdeIF0/edit === Ongoing Coding === {{{ cd web2py/applications/eden # Update your working directory with latest code from Trunk git pull upstream # Write Code # Quick review of code (no test code left in, etc) git diff # Check for any new files which need adding git status git add . # Commit Code (Note, no pushes to GitHub here) git commit -am "My Story: Part 1" . . . git commit -am "My Story: Part N" # Merge latest Trunk git pull upstream # Resolve any conflicts (see below for how) # Commit fixed code git add . git commit -a # Squash commits to as few as possible to keep revision history clean & make it easier to review the work # http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html git rebase -i # Push to your branch on GitHub git push }}} [[Image(https://docs.google.com/drawings/pub?id=1KElPNMq_annNSi_2f5r9grD-c0c_aZh1KBAOqSAtuPA&w=720&h=540)]] [[BR]] https://docs.google.com/drawings/d/1KElPNMq_annNSi_2f5r9grD-c0c_aZh1KBAOqSAtuPA/edit Once you have pushed to your branch on !GitHub, you will likely want this to be merged with Trunk - this should be done via a Pull Request. This is done on !GitHub: * https://github.com/mygitusername/eden/pull/new/(the branch name) [[Image(https://docs.google.com/drawings/pub?id=1QmGeuQvFpg3pDQpM9xu81V7MlVy4uU8EzVIRqQ14MwU&w=792&h=353)]] [[BR]] https://docs.google.com/drawings/d/1QmGeuQvFpg3pDQpM9xu81V7MlVy4uU8EzVIRqQ14MwU/edit ==== Resolving Merge Conflicts ==== If you encounter conflicts during the rebase, the conflicts will be tagged in the files with: {{{ <<<<<<< HEAD # Commits from Trunk ======= # Commits from >>>>>>> "My Story" }}} You can correct these conflict in your code text editor, then add them andcontinue the rebase: {{{ git add -u git rebase --continue }}} You can create the .THIS & .OTHER files using: {{{ git show :2:file.txt > file.txt.THIS git show :3:file.txt > file.txt.OTHER }}} You can use the changes to a file in the remote branch (theirs / OTHER): {{{ git checkout --theirs filename.c git add filename.c git commit }}} ...or the changes to a file in your local branch (ours / THIS): {{{ git checkout --ours filename.c git add filename.c git commit }}} ...or the changes to ALL files in the remote branch (theirs / OTHER): {{{ git checkout --theirs . # checkout our local version of all files git add -u # mark all conflicted files as merged git commit # commit the merge }}} Or the changes to ALL files in your local branch (ours / THIS) {{{ git checkout --ours . # checkout our local version of all files git add -u # mark all conflicted files as merged git commit # commit the merge }}} Although on Windows this seems by default to produce UTF-16 files! ('UCS-2 Little Endian'). A script to make this process easier for Windows users is attached: [http://eden.sahanafoundation.org/attachment/wiki/DeveloperGuidelines/Git/merge.cmd merge.cmd] ==== Reverting to last committed code ==== If you want to throw away all uncommitted changes (i.e. '{{{bzr revert}}}'), then: {{{ git reset --hard HEAD }}} ==== Rebasing after pushing to !GitHub ==== Squash your commits if they are not in between two executions of git pull or git merge: {{{ # Stash your current work git stash # N = number of commits to squash git reset HEAD@{N} git commit -am 'Your commit message for the one-big-commit' # Push to your branch on GitHub, overwriting any previous code there git push origin +master # Restore your work in-progress git stash pop }}} ==== Resetting to a previous commit ==== There are two types of resets soft and hard. A soft reset is done like this: {{{ git reset --soft HEAD@{N} }}} This resets your branch N previous commits (to a commit at a distance N from HEAD, the latest commit) but only in terms of git history. Hence your code remains untouched by git in a soft reset. A hard reset is done using: {{{ git reset --hard HEAD@{N} }}} This resets your branch N previous commits removing both history and changes to the file ever since. To remove commit from GitHub: {{{ # Rebase locally (this allows you to remove the last commit) git rebase -i HEAD~2 # Force update of GitHub git push origin +master }}} === Creating a second branch === You may want multiple branches in your repository, e.g. for working on separate tasks, or for experimentation, or as a backup before doing a rebase. === Creating a second working directory and repository === If you wish to have multiple directories containing different branches, you can run these as separate web2py applications. (Note this is not a standard manner of working when using git, and is generally only needed if you are working on multiple projects at the same time, and need to preserve their databases and other state.) * Create a fresh clone: {{{ cd web2py/applications git clone git@github.com:flavour/eden.git }}} * Setup a new repository on !GitHub -- see: https://github.com/repositories/new * Add remotes. {{{ git remote add upstream git@github.com:flavour/eden.git git remote add origin git@github.com:/.git }}} * Push to !GitHub: {{{ cd git push -u origin master }}} === Using Patches === If you have made changes to one branch & wish to backport them to another branch, then this is done most easily using a Patch: * http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git === Story Branches === The [http://blog.hasmanythrough.com/2008/12/18/agile-git-and-the-story-branch-pattern Story Branch] pattern allows pushing interim work to GitHub for review & also allowing contributing quick fixes to Trunk without needing to complete the interim work: {{{ git checkout -b git commit -a ... git commit -a # Quick review of code (no test code left in, etc) git diff master...HEAD }}} https://docs.google.com/drawings/d/1Vhvm1EmqWOVNZkZsiJ0MLLpdTl6H_ya263Tdb2HK1N0/edit == Developer Configuration == {{{ git config --global user.name "Your Name" git config --global user.email your@email.com git config --global github.user yourgithubusername git config --global github.token yourtoken git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin" git config --global merge.tool diffmerge git config --global diff.tool diffmerge git config --global difftool.diffmerge.cmd 'C:/Program Files (x86)/Git/etc/wrappers/git-diff-diffmerge-wrapper.sh' "$LOCAL" "$REMOTE" git config --global difftool.prompt false git config --global merge.tool diffmerge git config --global mergetool.diffmerge.cmd 'C:/Program Files (x86)/Git/etc/wrappers/git-merge-diffmerge-wrapper.sh' "$PWD/$LOCAL" "$PWD/$BASE" "$PWD/$REMOTE" "$PWD/$MERGED" git config --global mergetool.prompt false git config --global mergetool.trustExitCode false git config --global mergetool.keepBackup false }}} An alternative to diffmerge is Perforce's free P4V: * http://danlimerick.wordpress.com/2011/06/19/git-for-window-tip-use-p4merge-as-mergetool/ === Windows === Install [http://sourceforge.net/projects/console/ Console] & [http://www.sourcegear.com/diffmerge/downloads.php Diffmerge] & [http://markembling.info/2009/09/my-ideal-powershell-prompt-with-git-integration configure Powershell]. === Developer Tools === {{{.gitattributes}}} runs {{{version.py}}} to update the {{{VERSION}}} file on commit Possibly we could add a pre-commit hook to run tests, e.g. based on http://tech.yipit.com/2011/11/16/183772396/ or http://blog.penzilla.net/2011/09/git-pre-commit-hook-for-python-now-with.html === Notifications === You can subscribe to commits via RSS, e.g. to subscribe to Trunk, use: * https://github.com/flavour/eden/commits/master.atom If you wish to receive email notification of commits, then you can use an Email to RSS service like: * http://www.feedmyinbox.com * http://blogtrottr.com == Resources == * Community Book: http://book.git-scm.com * Tips & Tricks: http://gitready.com == History == === Why? === Sahana Eden has decided to move from !Bzr/LaunchPad to !Git/GitHub * The current repository is huge & bloated, taking too long to download. * Even simple changes take an age to Pull down to servers * Web2py no longer supports !Bzr/LaunchPad, so we want to be able to maintain a common tool to work with both repositories. * New developers are likely to be more familiar with !Git/GitHub === How? === The preferred approach is to have a clean repository, in order to get the maximum benefit from the migration...although it is technically possible to [http://fearthecowboy.com/2011/04/29/converting-bazaar-repositories-to-git/ migrate the commit history]. Commit History will instead be maintained on the !LaunchPad site as an archive ==== Migrating existing Branches ==== Merge branch with trunk using normal Bzr tools Assuming that you have already [https://github.com/flavour/eden/fork_select forked Eden Trunk], then you will need to create a new repository manually for additional branches, as you cannot [http://bitdrift.com/post/4534738938/fork-your-own-project-on-github fork your own project on GitHub]: * https://github.com/repositories/new {{{ cd web2py/applications git clone git@github.com:flavour/eden.git 2 }}} * Move {{{.git}}} & {{{.gitignore}}} from 2 to * Delete the rest of 2 * Edit {{{.git/config}}}: {{{ [remote "origin"] fetch = +refs/heads/*:refs/remotes/origin/* url = git@github.com:/.git }}} * Create the initial repo for this new branch {{{ cd git add . git commit -am "Initial Git version of My branch" git push -u origin master git remote add upstream git://github.com/flavour/eden.git }}}