Git tips
Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the page comments.
Many developers find git a useful tool to help them with moodle development, here some tips and workflows can be shared to help others.
Thorough Resolved Bug QA review with git
The power of having fast access to all of moodle commit history means we can search and checkout any point in moodle source code history which allows us to powerfully QA a bug.
Please note this workflow might not be ideal for all scenarios (for example if lots of work has been done in the same area since).
Example Workflow to QA MDL-16600:
First checkout a new branch for us to work on testing the bug in MOODLE_19_STABLE. We can delete this branch later, its less dangerous than playing any of our 'live' branches.
$ git checkout -b QA-MDL-16600 origin/MOODLE_19_STABLE Branch QA-MDL-16600 set up to track remote branch refs/remotes/origin/MOODLE_19_STABLE. Switched to a new branch "QA-MDL-16600"
Now search for any commits related to this bug fix:
$ git log --grep='MDL-16600' commit 1c2c8b09469ac27a3829e7267f399356a05b9810 Author: tjhunt <tjhunt> Date: Fri Sep 26 05:49:06 2008 +0000 MDL-16600 forcedownload broken for file resources.
In order to test that these commits fixed the bug, we will revert this commit, and then try to reproduce the reported bug:
$ git revert -n 1c2c8b09469ac27a3829e7267f399356a05b9810
Once we've reproduced the problem, we will reset our repository back to HEAD:
git reset --hard HEAD
Now if the bug is fixed, it can be closed and we can delete our branch:
git branch -D QA-MDL-16600
Backporting stuff from cvshead to stable git branches
I (Penny) have to do this all the time and it sucks. So I made a script to make it suck less.
http://cvs.moodle.org/contrib/tools/devtools/bugstogitformatpatch?view=markup
This little perl script takes a list of bug numbers, and generates patches that you can apply with git-am
I backported Tim's roles UI work and this is how I did it.
# make a new branch to work on $ git checkout -b mdl19-rolesbackport origin/MOODLE_19_STABLE
Now create some file that contains a list of bug numbers... In the case that there's only one, you can do:
$ echo MDL-xxxxx | bugstogitformatpatch --otherargs
Else you can do either of:
$ cat myplan | bugstogitformatpatch --otherargs $ bugstogitformatpatch --grepfile myplan
This file could be a whole file with documentation and everything, but the script does expect the bug numbers to be one per-line (but accepts other junk on the same line) and start with MDL-xxxx
The script has some other options, like where to put the patches it generates, and what the revlog spec should look like (by default it will just do origin/cvshead, but you can restrict it to a different branch or even abcdefg..12345678 if you want, anything git-log can understand - see man git-rev-parse).
See --help for more information.
Now the script will run and actually much faster than I expected, for Moodle's entire history. It will spit out git-format-patch formatted patches, which you can then happily apply with git-am.
TIP: For a large feature that goes into HEAD, it may happen that someone commits bugfixes to HEAD after you've backported it, which you'll then subsequently want to apply. To get around this, I did...
$ git tag rolesbackportedtohead origin/cvshead
After I was done... then the next time I wanted to run the script, I just used --revlist rolesbackportedtohere..origin/cvshead to only look at patches after the last time.
Local collaboration
You want to do this...
- git.moodle.org
- my organisation's git repository: aka shared repo (pulled from git.moodle.org)
- developer 1 (local git)
- developer 3 (local git)
- etc.
- my organisation's git repository: aka shared repo (pulled from git.moodle.org)
You want to collaboratively develop Moodle stuff pushing and pulling from your local shared repository. On top of that you want the upstream repository itself to pull updates from the upstream git.moodle.org.
Some names used in the examples:
- devel-1: the first developer
- devel-2: the second developer
- shared-repo: the name of the shared repository directory
- git-moodle: the name of the unix group needed to use the shared repository
Some assuptions for the examples:
- Linux/Unix environment
- All the repositories are on the same machine (if not, only need to change git transports from git:// to git+ssh://, etc.)
Devel-1: Create local repo and configure working environment:
cd /path/to/devel-1/dir mkdir devel-1.git cd devel-1.git git init git config --global user.name 'Devel-1 Real Name' git config --global user.email 'devel-1@email.address' git config --global i18n.commitEncoding 'utf8' git config --global i18n.logOutputEncoding 'utf8'
Get branches from git.moodle.org repo:
git remote add -t cvshead -t MOODLE_19_STABLE -t MOODLE_18_STABLE -m cvshead moodleorg git://git.moodle.org/moodle.git git fetch moodleorg
Create local (work) branches:
git branch --track cvshead-devel-1 moodleorg/cvshead git branch --track mdl19-devel-1 moodleorg/MOODLE_19_STABLE git branch --track mdl18-devel-1 moodleorg/MOODLE_18_STABLE
Create local shared repo and configure it:
cd /path/to/shared-repo/dir mkdir shared-repo.git cd shared-repo.git git --bare init --shared=all chmod g=rwxs,o=rx . # Give appropiate permissions to users in sudo chgrp -R git-moodle . # group 'git-moodle'.
Populate shared repo from local devel-1 repo:
cd /path/to/devel-1/dir/devel-1.git git remote add shared-repo /path/to/shared-repo/dir/shared-repo.git git push shared-repo +cvshead-devel-1: +mdl19-devel-1: +mdl18-devel-1:
Configure Devel-1 local repo branches to merge the right remote branch when pulling. We need to do this only for the first developer, as the shared repo didn't exist when we created the branches.
cd /path/to/devel-1/dir/devel-1.git git config branch.cvshead-devel-1.remote shared-repo git config branch.cvshead-devel-1.merge refs/heads/cvshead-devel-1 git config branch.mdl19-devel-1.remote shared-repo git config branch.mdl19-devel-1.merge refs/heads/mdl19-devel-1 git config branch.mdl18-devel-1.remote shared-repo git config branch.mdl18-devel-1.merge refs/heads/mdl18-devel-1
Create Devel-2 local repo and configure working environment:
cd /path/to/devel-2/dir git clone -o shared-repo /path/to/shared-repo/dir/shared-repo.git devel-2.git cd devel-2.git git config --global user.name 'Devel-2 Real Name' git config --global user.email 'devel-2@email.address' git config --global i18n.commitEncoding 'utf8' git config --global i18n.logOutputEncoding 'utf8'
Get branches from git.moodle.org repo:
cd devel-2.git git remote add -t cvshead -t MOODLE_19_STABLE -t MOODLE_18_STABLE -m cvshead moodleorg git://git.moodle.org/moodle.git git fetch moodleorg
Create local (work) branches from moodle.org:
git branch --track cvshead-devel-2 moodleorg/cvshead git branch --track mdl19-devel-2 moodleorg/MOODLE_19_STABLE git branch --track mdl18-devel-2 moodleorg/MOODLE_18_STABLE
From the shared-repo:
git branch --track cvshead-devel-1 shared-repo/cvshead-devel-1 git branch --track mdl19-devel-1 shared-repo/mdl19-devel-1 git branch --track mdl18-devel-1 shared-repo/mdl18-devel-1
Configure local branches to merge the right remote branch when pulling:
Nothing to do :-)
Now you can pull and push from any of the configured remote repositories (git.moodle.org and your shared local repo) by specifiying the remote repository name when using 'git pull' or 'git push'
If you are using git with a shared git repository, while 'ssh' access works it can be tricky to deal with permissions. 'Gitosis' allows multiple users all to access the repository using a single user on the server. Access control uses key-pairs. The article at scie.nti.st is a good introduction.
Git "Undo"
Well not really! If you are about to do a git operation and you are really not sure it will save you time to simply take a copy of the entire repository first. It is likely to take orders of magnitude less time to replace the repository with the copy than to unpick a broken repository.
Use 'git status' a lot
Before doing pretty much anything run 'git status' and read it. Make sure you are on the branch you think you are and that the list of changes to be committed (or not) is what you expect. It's easy to fix now than after you have done a commit (or worse still a push).
When you forget what all your branches are
gitk --all
is incredibly useful for showing the relationships between branches visually.
Know your verbose commands
You can get lots of information out of git, but it's not always completely obvious how. The following commands can be useful...
git branch -av
...shows all the branches (both local and remote), the last commit message and tells you (for a branch that tracks a remote) if it is forward or behind (or both!)
git branch -vv
...shows your local branches and which remotes they track. Very useful when you gave them a silly name and have forgotten what they track.
git remote -v
...lists all the remotes AND their full URLs for when you forget what they all are.
git remote show <remote_name>
...provides all the information you could ever want about a remote
More tips please
(Please add your own tips here!)