1

Point of my task : gather info about repo and place it to file while update hook and commit it ( perfectly with new commit).

Problems : when I'm doing commit -> it lockes origin repository and after this push is failing. my code looks like this :

#!/bin/bash

# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
export GIT_WORK_TREE=$PWD

# --- Safety check
if [ -z "$GIT_DIR" ]; then
        echo "Don't run this script from the command line." >&2
        echo " (if you want, you could supply GIT_DIR then run" >&2
        echo "  $0 <ref> <oldrev> <newrev>)" >&2
        exit 1
fi

version="${refname##*_}"
branchName="${refname##*/}"
filePath="_componentVersion/BranchVersion.ps1"

if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
        echo "usage: $0 <ref> <oldrev> <newrev>" >&2
        exit 1
fi

# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero="0000000000000000000000000000000000000000"
if [ "$newrev" = "$zero" ]; then
        newrev_type=delete
else
        newrev_type=$(git cat-file -t $newrev)
fi

case "$refname","$newrev_type" in
        refs/heads/*,commit)
                if [ "$oldrev " != "$zero" ]; then
                        version="${refname##*_}"
                        branchName="${refname##*/}"
                        filePath="_componentVersion/BranchVersion.ps1"

                        countOfCommits=$(git rev-list --count START_$version..$newrev)
                        countOfPushes=$(git log --pretty=oneline START_$version..$newrev | grep 'Issue nr: HOOK_$version' | wc -l)
                        countOfPushes=$(($countOfPushes+1))
                        echo git log --pretty=oneline START_$version..$newrev

                        message="
# -----------------------
# Brancht Version Info
# -----------------------

\$branch = '$version'
\$countOfCommits = $countOfCommits
\$countOfPushes = $countOfPushes # push
\$commitHash = '$newrev'
                        "

                        # credits go to https://stackoverflow.com/questions/9670302/commit-directly-to-a-bare-repository
                        # branch commit - here we will do the magic about count of commits and about count of pushes
                        # here we create file for info

                        # Empty the index, not sure if this step is necessary
                        git read-tree --empty

                        # Load the current tree. A commit ref is fine, it'll figure it out.
                        git read-tree "${newrev}"

                        # create blob from stdin
                        BLOB_ID=$(echo "$message" | git hash-object -w --stdin)

                        # update indexes in git
                        git update-index --add --cacheinfo 100644 "$BLOB_ID" "$filePath"

                        # Create a tree from your new index
                        TREE_ID=$(git write-tree)

                        # Commit it.
                        NEW_COMMIT=$(echo "Issue nr: HOOK_$version $message" | git commit-tree "$TREE_ID" -p "$oldrev")

                        # Update the branch
                        git update-ref "$refname" "$NEW_COMMIT" "$oldrev"
                fi

                # Done
                exit 0
                ;;
        *)
                # Other actions except commit to branch / for now - we won't check it
                exit 0
                ;;
esac

# --- Finished
exit 0

I'm working with bare repo. And example of commit taken from here Execte problem is

remote: error: cannot lock ref 'refs/heads/REL_7.0.0': ref refs/heads/REL_7.0.0 is at 54f2454ddab36eda001e27946733a7b0e981f097 but expected 89a3032e0bfb999273205e32b7f6d57173c4bd7e 

1 Answer 1

1

You can create commits.

You cannot update references that are locked, which includes the one that the update hook is being called for.

Since git push can push multiple reference names, there may be additional locked references. In general it's not a good idea to update anything that anyone might be git pushing inside a hook invoked by git push. In other words, don't try to update any branch or tag name. If you want to create new objects, attach them to some name outside these two name-spaces.

(Aside: the git read-tree --empty is not necessary, but it's a good idea to use a temporary index file anyway, rather than using the main index.)

4
  • So, If I've understood correctly - best variant is create other branch for this and commit changes there. Problem is -> I need this info to be saved in updating reference. Can you advise probable workaround?
    – xAqweRx
    Commented Aug 8, 2018 at 6:17
  • Ultimately, you can't change the update-in-progress: you can only accept it, or reject it. You could put the commit elsewhere, perhaps even in a different Git repository. That would probably be the safest approach.
    – torek
    Commented Aug 8, 2018 at 7:01
  • thx. Probably will implement it kind of combination of update and post-receive hooks. where update - will save somewhere info about what references was updated and post-receive will process them and update info only about references that was updated.
    – xAqweRx
    Commented Aug 8, 2018 at 7:33
  • You can make that work, but note that your post-receive hook will get all the same information that your update hook got (after all the updates have completed). The other main difference is that you get them all at once, on standard input, rather than being invoked once per update. Adding more commits to branch references at this point is OK, but note that you will be now be racing against other post-receive hooks from other git push commands.
    – torek
    Commented Aug 8, 2018 at 15:00

Not the answer you're looking for? Browse other questions tagged or ask your own question.