One of a series of test instances for migrating the Koha Wiki MediaWiki database.
For the current Koha Wiki, visit https://wiki.koha-community.org .Tips and tricks
From Koha Test Wiki MediaWiki Postgres
Home
Home
Home > Documentation
Home > Documentation
Koha > Technical > Development
Koha > Technical > Development > Git
Koha > Technical > Development > Quality Assurance Testing
Tips & Tricks > Tips & Tricks/Customising Notices and Slips > Tips & Tricks
Contents |
git tips and tricks
This page collect all git tips and tricks Koha developers have found
git
Hooks
A nice feature of git is hooks.
A hook is a small (or large) script that is executed before or after running some git command.
Hooks are located in the .git/hooks directory; To enable one simply add a file named after the hook point you wish to use to that directory and ensure it is executable.
pre-commit
This pre-commit hook will check for common coding issues before allowing you to complete a commit:
#!/usr/bin/perl use Modern::Perl; use File::Basename; use Term::ANSIColor qw(colored); $ENV{LOG} = "test"; my $nb_errors = 0; my @compiled_css = ( "staff-global", "opac" ); for my $filepath (`git diff --cached --name-only`) { chomp $filepath; next if not -f $filepath; my @file_infos = fileparse( $filepath, qr/\.[^.]*/ ); if ( grep( $file_infos[0], @compiled_css ) && $file_infos[2] eq ".css" ) { say colored( "You don't want to commit $filepath", 'red' ); $nb_errors++; } if ( $file_infos[2] =~ /^.pl|^.pm$/ ) { system(qq{/usr/bin/perl -wc $filepath}) == 0 or say "\n" and $nb_errors++; } elsif ( $file_infos[2] =~ /^.tt$/ ) { #TODO } elsif ( $file_infos[2] =~ /^.js$/ ) { #TODO } } my $filepath; for my $l ( split '\n', `git diff-index -p -M --cached HEAD` ) { if ( $l =~ /^diff --git a\/([^ ]*) .*$/ ) { $filepath = $1; } if ( $l =~ /console.log/ ) { say colored( "$filepath contains console.log ($l)", 'red' ); $nb_errors++; } elsif ( $l =~ /^\+ *warn Data::Dumper::Dumper / ) { say colored( "$filepath contains warn Data::Dumper::Dumper ($l)", 'red' ); $nb_errors++; } # This one could be uncommented when Koha will have the Logger module elsif ( $l =~ /^\+ *warn / ) { say "$filepath contains warn ($l)"; $nb_errors++; } elsif( $l =~ /\+ *\t/) { # fail also if there is some space before the tab say colored( "$filepath contains a tab, must use 4 spaces ($l)", 'red' ); $nb_errors++; } elsif ( $l =~ m/^<<<<<<</ or $l =~ m/^>>>>>>>/ or $l =~ m/^=======/ ) { say colored( "$filepath contains $& ($l)", 'red' ); } elsif ( $l =~ /(\+|-)\s*use/ ) { say colored( "Patch add or remove a use in $filepath: $l", 'red' ); say "You should run xt/find-undefined-subroutines.pl to check if nothing is broken"; $nb_errors++; } } if ($nb_errors) { say "\nAre you sure you want to commit ?"; say "You can commit with the --no-verify argument"; exit 1; } say colored( "Success, pre-commit checks passed", 'green' ); exit 0;
The above script checks that:
- All the perl scripts you want to commit are compiling (perl -wc)
- You are not committing compiled CSS files (CSS generated from SCSS).
- There are no trailing conflict markers (<<<<, >>>>>, =====)
- There are no trailing `warn` or `warn Data::Dumper::Dumper` additions
- There is no file called {something}.log
pre-applypatch
The pre-commit hook can also be useful as a pre-applypatch hook to catch issues with others bugs when applying via either `git am` or `git bz`.
pre-push
This pre-push hook will check for common coding mistakes before allowing the RM or RMaint to push to their community branch:
#!/usr/bin/perl use Modern::Perl; use List::MoreUtils qw( any ); use Term::ANSIColor qw(colored); my $RELEASE = '19.06.x'; # The branch you are managing/maintaining my $REMOTE = 'upstream'; # The name you gave to the remote for git.koha-community.org my $SIGNATURE = q|Martin Renvoize <martin.renvoize@ptfs-europe.com>|; # Your signature for sign-off lines my $remote = $ARGV[0]; my $minor = $RELEASE; my $upstream = ( $RELEASE =~ m{^\d\d\.(05|11)\.x$} ) ? $RELEASE : 'master'; $minor =~ s/x//g; if ( $remote eq $REMOTE ) { say "Running pre-push hook\n"; # Check branch my $current_branch = `git branch | grep \\* | cut -d ' ' -f2`; chomp $current_branch; if ( $current_branch ne $RELEASE ) { say colored( "Current branch is not $RELEASE", 'red' ); exit 1; } # Check commits exist my @commits = `git rev-list $REMOTE/$upstream..HEAD`; unless (@commits) { say colored( 'Hum... no commits to push?', 'green' ); exit 1; } # Check commit messages are well formed my @errors; for my $commit (@commits) { say colored("Working on $commit", 'green'); my $commit_message = `git log --format=%s -1 $commit`; if ( $commit_message !~ m|^Bug\s\d{4,5}: | ) { push @errors, colored( "Does not start with 'Bug XXXXX: ' - $commit", 'red' ); } if ( $commit_message =~ m|DO NOT PUSH| ) { push @errors, colored( "Comit contains DO NOT PUSH - $commit", 'red'); } if ( $commit_message =~ m|DBRev|i and not $commit_message =~ m|DBRev $minor| ) { warn $commit_message; push @errors, colored( "DBRev is wrong, should start with 'DBRev $RELEASE'", 'red' ); } my $body = `git log --format=%b -1 $commit`; $body =~ s|\n\s*|\n|g; if ( $body !~ m|\n?Signed-off-by: $SIGNATURE| ) { push @errors, colored( "No Signed-off-by line - $commit", 'red' ); } my $author_name = `git log --format=%an -1 $commit`; if ( $author_name eq 'John Doe' ) { push @errors, colored( "Bad author name - $commit", 'red' ); } my $author_email = `git log --format=%ae -1 $commit`; if ( $author_email eq 'you@example.com' ) { push @errors, colored( "Bad author email - $commit", 'red' ); } } # Check for remaining atomicupdate files my @atomicupdate_files = `git show HEAD:installer/data/mysql/atomicupdate/|tr -s '\\n' | grep -v '^tree'|grep -v 'README'|grep -v skeleton`; chomp for @atomicupdate_files; for my $atomic (@atomicupdate_files) { push @errors, colored( "Atomicupdate file exists - $atomic", 'red' ); } my @dbrev_files = `git show HEAD:installer/data/mysql/db_revs/|tr -s '\\n' | grep -v '^tree'`; chomp for @dbrev_files; for my $f ( @dbrev_files ) { my $mode = (stat("installer/data/mysql/db_revs/$f"))[2] & 07777; push @errors, "dbrev file is missing the +x flag - $f" if $mode != 0775; } # Check for missing CSS Compiles my $compiled = `yarn build && yarn build --view=opac`; my @css_changes = `git diff --name-only`; chomp for @css_changes; for my $css_change (@css_changes) { push @errors, colored( "CSS file changes exist - $css_change", 'red' ); } # Report any errors if (@errors) { say colored($_, 'red') for @errors; exit 1; } say colored("Passed tests, pushing...", 'green'); } exit 0;
This hook will prevent:
- to push a local branch that is not named "$RELEASE"
- to push commits that are not signed off by the RM/RMaint
- to push commits that do not start with "Bug XXXXX: "
- to push DBRev commits that do not correctly formatted ("DBRev $RELEASE")
- to push atomicupdate files
Display the branch you're on
If you want to permanently display the branch you're on, edit your .bashrc file and add the following at the end:
#prompt git GIT_PS1_SHOWDIRTYSTATE=1 GIT_PS1_SHOWUNTRACKEDFILES=0 GIT_PS1_SHOWSTASHSTATE=1 GIT_PS1_SHOWUPSTREAM="verbose" PS1='\D{%H:%M} \[\033[1;35m\]\w$(__git_ps1 " \[\033[1;34m\](%s)")\[\033[0m\]\$ '
your display will look like this:
17:47 ~/koha.dev/koha-community (new/bug_7190 $%)$
displaying the directory you're on, the branch, and some informations about the status of your working directory
Git aliases to simplify command tasks
If you have Git-BZ installed, you can add the following aliases to your .gitconfig file to make applying a patch and reattaching it with your signoff a 1-command affair:
[alias] so = !sh -c 'prove t xt && git commit --amend -s && git bz attach -e $1 HEAD' - qa = !sh -c 'git fetch origin master && git checkout -b bug$1-qa origin/master && git bz apply $1' - gr = log --graph --full-history --all --color --pretty=tformat:"%x1b[31m%h%x09%x1b[32m%x1b[0m%x20%d%s%x20%x1b[33m(%an)%x1b[0m" qa2 = "!f() { c=`expr $1 - 1`; git filter-repo --message-callback 'return message + b\"\\nSigned-off-by: Full Name <email>\"' --refs HEAD~$c^..; }; f"
You may need to install git filter-repo first.
git so ####
Runs automated tests, signs off on the patch and attaches it to the bug report, obsoleting the unsigned patch.
git qa ####
Fetches the latest master from git.koha-community.org, creates a new branch off that for the bug you're testing, then applies the patch from Bugzilla
git gr
Not BZ-specific, but this draws a character-mode graph showing the branch structure and displays it through your pager.
git qa2 N
Not BZ-specific, this alias will add your signature to N patches. git qa2 3 => deal with 3 patches