我花了几个小时努力让 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
会起作用,但不会被提交。
有效示例:
- 您修改了一个文件,并将其添加(例如
gitignore
)
$> git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitignore
- 运行提交。首先,
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
- 您可以看到消息表明
file
已提交。git status
现在输出:
On branch master
nothing to commit, working tree clean
不起作用的示例
- 您无需添加任何内容。您当然可以运行,
git add
但它不会执行任何操作。git status
结果为:
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
- 运行提交。钩子将创建
file
。但提交消息表明他什么也没做。
--- Dataset Pre-Commit Hook ---
--- Done ---
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
- 验证状态
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
- 您可以看到文件确实已被修改,并且已添加,但尚未提交。您需要
git commit
再次运行才能使其生效。
我尝试将其添加为post-commit
钩子,但没有成功。如果有人知道这种情况的解决办法,我会很想知道。