Git/Tips

< Git

A list of Git tips and tricks

Dealing with old branches

If you have been working with git for a while you probably have a bunch of old crufty branches laying around that you don't need anymore. The ones you definitely don't need anymore are ones that have already been merged back to master. You can identify these with:

$ git branch --merged

Similarly, when submitting a change for review, you can have your branch automatically deleted once it's been merged by Gerrit:

$ git review -f

Pre-commit checks

Git allows you to define checks a commit has to pass via hooks (see githooks(5) for details). You should keep in mind that you have to define hooks separately for every (for example extension's) repository and that they are not copied by git clone, so you have to create some procedure suiting your personal work patterns for how to keep them organized.

Start by enabling the pre-commit sample installed by Git. It disallows non-ASCII filenames and trailing whitespace.

Disallow commits to master

Committing to master in your local repository usually isn't what you want. To disable, put this sniplet at the top:

# Disallow commits to master.
if [ "$(git symbolic-ref HEAD)" = "refs/heads/master" ]; then
	echo "Error: Attempt to commit to master."
	echo
	exit 1
fi

You could also disallow commits to other branches (REL1_20, etc.), but protecting against master is enough in most cases.

Run php -l on PHP files

It's probably a good idea to check whether any PHP files you added or changed pass a simple php -l test. To enable this, put this sniplet before the final exec git diff-index line:

# Run lints on added or changed files.
git diff --cached --name-only --diff-filter=ACM -z $against |
while read -d '' -r FILENAME; do
    case "$FILENAME" in
        *.php)
            if [ "x$MW_GITPHPLINT" != "xfalse" ]; then
		if ! git show :"$FILENAME" | php -l; then
                    echo "   in '$FILENAME'"
                    exit 1
                fi
            fi
            ;;
    esac
done

STATUS=$?
if [ $STATUS -ne 0 ]; then
    exit $STATUS
fi

Running test suites

As the pre-commit checklist suggests, you should run tests before submitting a change. In a rational world, this tedious task is left to a robot, in the real world where despite frequent a/b tests for UI tidbits this isn't even on the radar, you have to build the robot yourself. Thankfully, Git offers all that is needed in the hooked form of post-commit.

The following example somewhat tests the parser and the SQLite backend (cf. the Jenkins jobs repository for further inspiration):

#!/bin/sh

at now <<EOF
WWWDIR=~/public_html/w-sqlite &&
rm -Rf "\$WWWDIR" &&
git clone ~/public_html/w "\$WWWDIR" &&
cd "\$WWWDIR" &&
mkdir data &&
nice php ./maintenance/install.php --confpath . --dbtype=sqlite --dbpath=./data --showexceptions=true --pass testpass --server http://localhost/ sqlitetest WikiAdmin &&
nice php ./tests/parserTests.php &&
nice composer phpunit:entrypoint -- --group Parser --exclude-group Broken,ParserFuzz,Stub --
EOF

Obviously, it's very necessary to adapt this hook to your personal workspace and also not use the same for core as for extensions. Running the test suite as an at job allows you to continue working while the test runs in the background and you will be mailed the results once it ends. This setup assumes that you run one test suite at a time; if you want to run more in parallel, you can reference the SHA1 of HEAD in WWWDIR or even try git describe --tags but be reminded that each clone will consume more than 200 MByte of disk space.

What tests you should run depends on your field of work. If you are working on parser bits, running those tests may be enough. If you plan complex changes to the database schema, you can test fresh installs and running update.php from older installations. If you are working on extensions, you can clone master and tags (not branches, the latter are moving targets) 1.18.4 and 1.19.2 and see whether your code is still compatible with them.

If you develop on a box with few resources, but have access to more powerful machines on the net, you can create bare repositories on the latter and use the hook post-update in a similar fashion on them (the commit is passed as $1). You then just have to git push $POWERFULMACHINE to start the test suite.

View source code

We use a Gerrit plugin called "Gitiles" to browse the repository as a whole:

There are also alternatives:

See also