如何提交 Git 中预提交钩子修改的文件

如何提交 Git 中预提交钩子修改的文件

我花了几个小时努力让 git 使用 metastore 存储文件的元数据(权限/标志/等),并且我用它来做hooks/pre-commit这个。

脚本正确调用,文件“metadata”被修改但未添加到提交中。

我尝试打电话:

git add ./metadata 

git add -u ./metadata

来自预提交脚本,但没有效果。文件最终未提交并标记为已修改或已暂存但从未提交。

有什么办法可以让它工作吗?基本上,我希望它在每次提交时更新并提交文件“元数据”(最好是同一次提交,这样我可以在签出后恢复所有权限)

谢谢!

PS 如果您想知道我为什么需要这个,答案是我存储了需要权限/suid 标志等的嵌入式设备的操作系统文件。

答案1

你可以做这样的事情:

#!/bin/sh
#

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

git add ./version.js

它的作用:改变字符串var app_version = "0.1.1";var app_version = "0.1.2";并将文件添加回 git commit 进程。提交时将包含最新的更改。

答案2

我找到了解决方案。问题是,当从预提交钩子文件修改时,它是唯一被修改的文件 - 提交没有发生。在测试时,我只在“元数据”文件中进行了更改,这就是为什么它对我不起作用的原因。

当我修改 repo 中的其他文件并添加/rm 新文件时 - 元数据文件就会被正确提交!

底线:为了提交从预提交钩子修改的文件,git 需要一些其他暂存的更改,否则提交将不会发生(可能是 git 错误地检测到没有任何内容可提交)。

对我来说,这似乎有点出乎意料。我在 git 1.8 和 git 2.0 中测试了这一点,行为是相同的。

答案3

pre-commit为了以不干扰未暂存更改的方式(即友好)修改钩子中的文件git-add -p,您需要编辑索引中的文件版本。

下面是一个示例pre-commit钩子更新文件头中的时间戳版本号

#!/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

答案4

假设你有一个预提交钩子可以执行以下操作:

#!/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

它会起作用如果且仅当,已经有内容需要提交。但不必是同一个文件。如果没有内容需要提交,git addgit add file会起作用,但不会被提交。

有效示例:

  1. 您修改了一个文件,并将其添加(例如gitignore
$> git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   .gitignore
  1. 运行提交。首先,pre-commit钩子将运行并创建file。然后它将提交。
--- 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. 您可以看到消息表明file已提交。git status现在输出:
On branch master
nothing to commit, working tree clean

不起作用的示例

  1. 您无需添加任何内容。您当然可以运行,git add但它不会执行任何操作。git status结果为:
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
  1. 运行提交。钩子将创建file。但提交消息表明他什么也没做。
--- Dataset Pre-Commit Hook ---
--- Done ---
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
  1. 验证状态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. 您可以看到文件确实已被修改,并且已添加,但尚未提交。您需要git commit再次运行才能使其生效。

我尝试将其添加为post-commit钩子,但没有成功。如果有人知道这种情况的解决办法,我会很想知道。

相关内容