r-预提交钩子后:git add使暂存文件消失



我正在尝试设置一个本地预提交挂钩。它应该检查是否有任何编辑过的文件是根据tidyverse样式指南(使用styler)进行样式设置的。因为我的公司不允许直接访问github,所以我不能使用precommit,并且必须通过编辑.git/hooks/pre-commit文件来设置挂钩。

设置

这就是我尝试的:我的.git/hooks/pre-commit

#!/bin/bash
set -eo pipefail
CHANGED_FILES=$(git diff --name-only --cached --diff-filter=ACMR)
get_pattern_files() {
pattern=$(echo "$*" | sed "s/ /$\|/g")
echo "$CHANGED_FILES" | { grep "$pattern$" || true; }
}
R_FILES=$(get_pattern_files .R)
# if R_FILES is not empty, run Rscript
if [[ -n "$R_FILES" ]]
then
Rscript ./style.R $R_FILES
fi
# exit with 1, if Rscript failed
if [ $? -eq 0 ]; then
exit 0
else
exit 1
fi

和我的./style.R

#!/usr/bin/env Rscript
args <- commandArgs(trailingOnly = TRUE)
output <- styler::style_file(path = args)
if (any(output$changed) == TRUE) {quit(status = 1)}

问题

当我编辑一个文件时,我可以在不同的中看到它

user@machine:~/r_template$ git diff
diff --git a/src/main.R b/src/main.R
index 8d2f097..dd1272d 100644
--- a/src/main.R
+++ b/src/main.R
@@ -1 +1 @@
-1 + 1
+1 +1           <-- this is what I have changed in the file

我用git add -u添加它,然后gitcommit。钩子被调用,并按预期中止提交(因为Rscript以状态1退出)。

user@machine:~/r_template$ git commit
Styling  1  files:
src/main.R ℹ
────────────────────────────────────────
Status  Count   Legend
✓       0       File unchanged.
ℹ       1       File changed.
x       0       Styling threw an error.
────────────────────────────────────────
Please review the changes carefully!

并且可以看到(预期的)编辑文件

user@machine:~/r_template$ git status
On branch feature/precommit-hooks
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified:   src/main.R
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified:   src/main.R

styler::style_file()进行预期更改

user@machine:~/r_template$ git diff
diff --git a/src/main.R b/src/main.R
index dd1272d..8d2f097 100644
--- a/src/main.R
+++ b/src/main.R
@@ -1 +1 @@
-1 +1
+1 + 1       <-- this is done by styler::style_file()

好的,所以接下来我想进行这个编辑,所以我git add -u。但后来发生了一些事情,我无法理解

utxkanal@vlx00950:~/r_template$ git status
On branch feature/precommit-hooks
nothing added to commit but untracked files present (use "git add" to track)

集结区完全是空的。尽管如此,src/main.R的变化仍然有效。这里发生了什么?

了解发生了什么的诀窍是:暂存区从不为空,也从不包含任何更改显而易见的回答是什么是f-,你显然不知道你在说什么,因为git status显示了一个空的暂存区,git diff显示了变化。是的,他们确实如此。诀窍是这些都是战略性的谎言

正如艾米莉·狄金森的诗《实话实说,但要倾斜说》所指出的那样,试图立即看到整个画面是压倒性的。Git的索引/暂存区的全部事实是,它包含每个文件的完整副本,可以提交。也就是说,当前提交始终存在三个副本:

  • 在当前提交本身中有一个一直冻结的。这就是你开始的。

  • 有一个";介于";版本,我放在这里是因为它是";在";,但还没有描述。

  • 工作树中有一个可用的(可编辑、可查看,通常对工作有用)副本。这就是你做事的方式。

;介于";版本只是Git暂存区中每个文件的完整副本,Git也将称为索引

git diffgit diff --cached显示更改时,Git所做的就是用两个快照玩"发现差异"游戏。有两张完整的照片,但两者有一些不同。Git从diff输出中省略了所有相同的东西,因为这些东西很无聊!我们想知道有什么不同

git status也发生了同样的事情,只是它没有向我们显示什么不同,而是"告诉"我们哪些文件名具有一个或多个差异。所以这个:

user@machine:~/r_template$ git status
On branch feature/precommit-hooks
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified:   src/main.R

意味着当Git将HEAD(当前)提交中每个文件的完整快照与暂存区中每个文件的<em]完整快照进行比较时,有一个文件不同:src/main.R。同时,第二部分:>

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified:   src/main.R

意味着当Git(单独)将暂存区中的完整快照与工作树完整快照进行比较时,有一个文件不同:src/main.R(再次)。

如果我们现在更改src/main.R索引(也称为暂存)副本——我们可以随时批量替换它,格式化挂钩也可以这样做——那么HEAD与索引的区别就会改变。也许它甚至完全消失了!另外,从索引到工作树的差异也会发生变化。

在这种特殊情况下,发生的情况是冻结的、归档的HEAD副本和工作树副本已经匹配。只有索引/暂存区域副本不同。运行git add src/main.R告诉Git:将索引副本替换为工作树副本。它做到了,现在三个副本都匹配了。

脚注:";暂存区从不为空,也从不包含任何更改";这显然是夸大其词。这也是错误的,因为可以通过删除其中的每个文件来拥有一个完全空的暂存区。这样做是不正常的。当你第一次提交时,你通常唯一的时间是在一个全新的、完全空的存储库中。但记住索引/暂存区域有每个文件的完整快照仍然是一个很好的方法。事实上,关键是索引区域中的完整快照实际上是您计划放入下一次提交的快照。

(还有更棘手的多个索引/分期区域的情况。)

相关内容

  • 没有找到相关文章

最新更新