What needed to be done after the pre-commit hook was launched?

To intercept the pre-commit, which modifies the staged files, I need to figure out what needs to be done after the hook has been started.

The prefix hook applies pretty nice prints to files that need to be committed. The hook performs the following tasks:

  • replace tabs with spaces
  • remove trailing spaces at the end of lines
  • delete double blank lines *)
  • if not, add an empty line at the end of the file *)

Actions marked with *) are those that cause the problem described below.

After this has been done, the hook adds the modified file to the index using git add $filename . Thus, the whole file will be delivered, and I can no longer make small portions (i.e. Hunks) of the modified file.

Of course, I could git add --no-verify and bypass the hook, but this option is not available when using git gui . Also, I want to apply pretty-printed information in staged lines of a file, so hook traversal is not my goal.

Is there any way to find out what needs to be added to the index after pretty printing has been applied so that I can create the right content after the hook has been launched, and not to set up the whole file?


Change 1:
While the answer provided by David Brigada seems promising, it doesn't work: git stash --keep-index exits the post changes integrity (which is the good part), but (at least on msysgit), it puts all the changes in stash (not only uninstalled). This leads to merge conflicts when attachments appear in the WC, because staged lines can be changed.


Edit 2:
Also, David's updated answer does not lead to success, since git refuses to combine the cache into a dirty toilet.


Edit 3:
A response from larsks indicates the use of .gitattributes . At first glance this seems correct, but I find it rather confusing that the verified version was run through a filter, and the WC is different from the verified version. At least that was my experience and is reinforced by the following remark in the Git Book :

If you copy these changes and check the file again, you will see that the keyword is correctly replaced

I need to delete the file and then check it again to see the changes that were applied by the filter. Never! Any clues?

+7
source share
5 answers

I'm not sure if the pre-commit hook is the right place to do this kind of work. Git has a filtering mechanism that allows you to apply commit / check filters to documents through .gitattributes ; The Pro Git book contains examples that use this filtering mechanism to automatically apply the indent program to C source files.

+2
source

You can put the changes that you did not set for commit in the wallet in the pre-commit script, and then pull them out when done. The --keep-index option saves only those changes that you have not added to the index (do not run git add on), and the --quiet options suppress notifications that you create and destroy the cache.

The way you described is not exactly the canonical "git to do this" way, most of the pre-commit scripts I have seen only check for the wrong style and then exit the commit if they find something. That way, you don't have a pre-commit script, inadvertently rewrite some file that for some reason should have tabs (like test data) --- you could just restart the commit with -no-verify once you were sure mistakes should have been there.

I have a simple pre-commit script here. Basically it just runs the git base diff-index test --check, but it uses the git prefix to work only with the changes it needs.

 #!/bin/sh if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi git stash save --keep-index --quiet git diff-index --check --cached $against -- RETVAL=$? git stash pop --quiet exit $RETVAL 

Update:

If you try to use this strategy with a script that modifies the content you want to commit, you will get merge conflicts. We need to extract the pop-up message from the pre-commit script and perform an explicit merge in the post-commit script.

 #!/bin/sh git stash save --keep-index --quiet # Add your script to prettify the code here ... git add . 

Now the post-commit script looks like this:

 #!/bin/sh git merge stash@ {0} -s recursive -Xtheirs git stash drop --quiet stash@ {0} 

Merging recursive with theirs parameter should contain script changes, if possible.

+2
source

I am not 100% sure, I understand the goal, but maybe you could try the following approach. Ask your hook to create a patch instead of writing changes to disk. (You can do this, for example, in Python, using the difflib module, or write a temporary file and upload it to diff .) Then use git apply (with --cached and other flags, respectively) to apply your patch to the index, as well to the working tree (manually or automatically with a hook).

0
source

Since my goal does not seem to be achievable, I helped me with another solution:

I only process parts of the files when I am in git gui . Fortunately, git gui allows you to add custom commands to the Tools menu. I installed a script called hooks.sh that receives one parameter: enable or disable . This script is added to the Tools menu, once with enable , once with disable as a parameter.

That way, I could comfortably disable the hook when placing only part of the file, then commit and then re-enable the hook.

There you go:

 #!/bin/sh ################################################################################ # hooks.sh # # enable or disable git hooks. # ################################################################################ THEHOOK=pre-commit # which hook to work with ENABLEDFILE=./.git/hooks/$THEHOOK # original name of the file DISABLEDFILE=$ENABLEDFILE.disabled # disabled name of the file OLDFILE='' # for mv command: old name NEWFILE='' # for mv command: new name # parse parameters case $1 in disable) OLDFILE=$ENABLEDFILE NEWFILE=$DISABLEDFILE ;; enable) OLDFILE=$DISABLEDFILE NEWFILE=$ENABLEDFILE ;; *) echo -e "operation:\n $0 enable to enable the hook\n $0 disable to disable the hook" exit 1 ;; esac if [ -e $OLDFILE ] then mv $OLDFILE $NEWFILE else echo "nothing to do" fi 
0
source

You want to have a pre-commit hook that executes the actions you described, and then also hook-commit-msg.

Here is how I would solve the problem:

  • Add the following hook to pre-lock:

     #!/bin/sh git diff --cached --name-only -z --diff-filter=ACM | xargs -r0 YOUR_SMUDGE_SCRIPT git diff --cached --name-only -z --diff-filter=ACM | xargs -r0 git add -u -v -- 
  • Add the following commit-msg hook:

     #!/bin/sh awk '!/^[[:space:]]*(#|$)/{exit f++}END{exit !f}' "$1" && exit # NOTREACHED unless commit was aborted git diff --cached --name-only -z --diff-filter=ACM | xargs -r0 YOUR_CLEAN_SCRIPT git diff --cached --name-only -z --diff-filter=ACM | xargs -r0 git add -u -v -- 

Taking care of replacing YOUR_CLEAN_SCRIPT and YOUR_SMUDGE_SCRIPT with the name of the command you want to run that will perform the actual cleanup / blur procedures. The smudge procedure should expand the keywords (pre-commit occurs), and the clean procedure should cancel the changes (occurring when the commit fails). These scripts will transfer the files that need to be changed (previously set for another editing).

0
source

All Articles