9

Im struggling for a couple of hours to make git store metadata (permissions/flags/etc) of the files using metastore and I use hooks/pre-commit for this.

The script is invoked correctly, and the file "metadata" is modified but not added into commit.

I tried calling:

git add ./metadata 

and

git add -u ./metadata

from the pre-commit script, but there is no effect. The file ends up uncommited and marked as modified or staged BUT not commited, ever.

Is there any way to make this work? Basically, I want it to update and commit the file "metadata" on each commit (preferably, as the same commit, so I can restore all permissions after checkout)

Thanks!

P.S. If you are wondering why I need this, the answer is I store OS files for an embedded device which needs permisions/suid flags etc.

1
  • It should work, maybe you are doing something wrong. Pre-commit hook is executed automatically when you do "git commit". It must have an executable bit set. So try to add some files to the staging are manually and then do "git commit". After that do "git show" to see what changes have been introduced in this commit and see if metadata has been committed. Jun 15, 2014 at 22:15

4 Answers 4

2

You can do something like this:

#!/bin/sh
#

perl -i -pe 's/var app_version = "\d+\.\d+\.\K(\d+)/ $1+1 /e' ./version.js

git add ./version.js

What it does: It changes the string var app_version = "0.1.1"; to var app_version = "0.1.2"; and adds the file back to the git commit process. When you commit the latest change will be included.

2
  • 3
    wrong question?
    – dimovnike
    Oct 18, 2014 at 14:14
  • 1
    The problem here is that you will commit all changes in that particular file. Not only the previously staged changes. Might work for files that only contain the version though. Jun 26, 2017 at 9:33
1

I have found the solution. The problem is that when modified from pre-commit hook file is the only modified file - the commit is not happening. While testing this, I was making changes only in the "metadata" file and thats why it did not work for me.

As soon as I modify some other files in the repo add add/rm new files - the metadata file is properly commited!

Bottom line: In order to commit the modified files from pre-commit hook, git needs some other staged changes, otherwise the commit won't happen (probably, git erroneously detects that there is nothing to commit).

This seems a bit unexpected behaviour to me. I tested this in git 1.8 and git 2.0 the behaviour is the same.

3
  • I got the same problem, but having other staged files changed doesn't solve the issue. Git doesnt pick up changes made by pre-commit in my case..
    – frhd
    Oct 1, 2014 at 15:32
  • make sure u do git add for the canges made by pre-commit script (at the end of the script).
    – dimovnike
    Oct 1, 2014 at 19:10
  • I cant do that. I'm getting an index.lock error, since git-commit is calling the pre-commit. Does it work for you?
    – frhd
    Oct 1, 2014 at 19:37
1

To modify a file in the pre-commit hook in a way that doesn't interfere with unstaged changes (i.e. git-add -p friendly), you need to edit the version of the file in the index.

Here's an example pre-commit hook which updates a timestamp-like version number in a file header:

#!/bin/bash
set -eEuo pipefail

date=$(date +%Y%m%d%H%M)

# Enumerate *.el files that have been edited for this commit
git diff-index --name-only --cached -z HEAD |
    grep -z '\.el$' |
    while read -r -d '' fn
    do
        # Patch index
        blob_sha1=$(git show :"$fn" |
                        sed "s/^;; Version:  .*/;; Version:  $date/" |
                        git hash-object -w --stdin)
        printf '100644 blob %s\t%s\0' "$blob_sha1" "$fn" |
            git update-index -z --index-info

        # Patch working tree to match index
        sed -i "s/^;; Version:  .*/;; Version:  $date/" "$fn"
    done
0

Imagine you have a pre-commit hook that does this:

#!/bin/bash

echo "--- Dataset Pre-Commit Hook ---"

DATASET_REPO_PATH="$(pwd)"

python3 -m my_script_that_generates_or_modifies_a_file
git -C $DATASET_REPO_PATH add file

echo "--- Done ---"
exit

It will work IF AND ONLY IF, there was already something to be commited. It does not have to be the same file tho. If there was nothing to be commited, the git add git add file will work, but will not be commited.

Example that works:

  1. You changed a file, and added it (for example, the gitignore)
$> git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   .gitignore
  1. Run commit. First, the pre-commit hook will run and create file. Then it will commit.
--- Dataset Pre-Commit Hook ---
--- Done ---
[master (root-commit) 2ba2f7c] First commit
 3 files changed, 34 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 file
  1. You can see the message says file was commited. And git status now outputs:
On branch master
nothing to commit, working tree clean

Example that DOES NOT work

  1. You have nothing to add. You can of course run git add but it will do nothing. git status gives:
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
  1. Run commit. The hook will create file. But the commit message says he did nothing.
--- Dataset Pre-Commit Hook ---
--- Done ---
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
  1. Verify the status git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   file
  1. You can see that file was indeed modified, and that it was added, but yet not commited. You need to run git commit again for it to work.

I tried adding that as a post-commit hook but got no luck. If someone knows a fix for this case, I would love to know.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .