view raw
jjmerelo jjmerelo - 6 months ago 58
Git Question

Can you change a file content during git commit?

One of the things I keep in my open novel in GitHub is a list of words I would like to set automatically the first line, which is the number of words in the dictionary. My first option is to write a pre-commit hook that reads the file, counts the words, rewrites the first line and writes it back again. Here's the code

my ($git) = @_;
my $branch = $git->command(qw/rev-parse --abbrev-ref HEAD/);
say "Pre-commit hook in $branch";
if ( $branch =~ /master/ ) {
my $changed = $git->command(qw/show --name-status/);
my @changed_files = ($changed =~ /\s\w\s+(\S+)/g);
if ( $words ~~ @changed_files ) {
my @words_content = read_file( $words );
say "I have $#words_content words";
$words_content[0] = "$#words_content\n";
write_file( $words, @words_content );

However, since the file has already been staged, I get this error

error: Your local changes to the following files would be overwritten
by checkout:
Please, commit your changes or stash them
before you can switch branches.

Might it be better to do it as a post-commit hook and have it changed for the next commit? Or do something completely different altogether? The general question is: if you want to process and change the contents of a file during commit, what's the proper way of doing it?


It turns out you can run "hooks" - they are actually handled by another mecanism - when staging files (at git add time) :

(scroll down a bit to the "smudge/clean" diagram)

Here is what I understood :

  1. edit the .gitattributes, and create rules for the files which should trigger a dictionary update :

    novel.txt updateDict

  2. Then, tell Git what the "updateDict" filter does on smudge (git checkout) and clean (git add) :

    $ git config --global filter.updateDict.clean countWords.script

    $ git config --global filter.updateDict.smudge cat