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
PRE_COMMIT { 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: text/words.dic Please, commit your changes or stash them before you can switch branches. Aborting
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?
Find the commit you want, change pick to e ( edit ), and save and close the file. Git will rewind to that commit, allowing you to either: use git commit --amend to make changes, or.
You can change the most recent commit message using the git commit --amend command. In Git, the text of the commit message is part of the commit. Changing the commit message will change the commit ID--i.e., the SHA1 checksum that names the commit. Effectively, you are creating a new commit that replaces the old one.
The Basic of the Amend Command Here you can edit your commit message. Do as you wish and then save the file. If you don't want to change the message, just save the file without changing it. Now the changes you did on the last commit and after it will be in the same commit!
The actual commit stuck in by git commit
is whatever is in the index once the pre-commit hook finishes. This means that you can change files in the pre-commit hook, as long as you git add
them too.
Here's my example pre-commit hook, modified from the .sample:
#!/bin/sh # # An example hook script to verify what is about to be committed. # [snipped much of what used to be in it, added this -- # make sure you take out the exec of git diff-index!] num=$(cat zorg) num=$(expr 0$num + 1) echo $num > zorg git add zorg echo "updated zorg to $num" exit 0
and then:
$ git commit -m dink updated zorg to 3 [master 76eeefc] dink 1 file changed, 1 insertion(+), 1 deletion(-)
But note a minor flaw (won't apply to your case):
$ git commit git commit updated zorg to 4 # On branch master # Untracked files: [snip] nothing added to commit but untracked files present (use "git add" to track) $ git commit updated zorg to 5 # Please enter the commit message for your changes. Lines starting [snip - I quit editor without changing anything] Aborting commit due to empty commit message. $ git commit updated zorg to 6 # Please enter the commit message for your changes. Lines starting
Basically, because the pre-commit hook updates and git add
s, the file keeps incrementing even though I'm not actually doing the commit, here.
[Edit Aug 2021: I need to emphasize that I do not recommend this approach. Note that there are some oddball cases that can come up when using git commit -a
, git commit --include
, and git commit --only
, including the implied --only
that is inserted if you name files on the command line. This is due to the fact that this kind of git commit
creates a second, and sometimes even a third, internal Git index. Any git add
operations you do inside a hook can only affect one of these two or three index files.]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With