可以在预提交 git hook 中重新暂存文件吗?

2024-01-12

我制作了一个 powershell 脚本,为项目中的某些文件添加标头。我想在代码被推送到 GitHub 的过程中运行它,以便 GitHub 存储库中的所有此类文件都附加标头,从而无需手动运行脚本。

问题是,当我修改预提交 git 挂钩中的文件时,这些更改不会重新暂存,因此我基本上必须暂存、提交,然后再次暂存才能提交标头。

有没有一个好的方法来处理这个问题,或者将 powershell 脚本的执行与 git 流程分开是更好的做法吗?


TL;DR

主题行中的问题的答案是“是的,但是”。 :-) 我将在这里稍微改一下措辞,以便我们可以讨论所有技术细节。 “但是”是如果你使用的话会有一个很大的惊喜git commit --only。我好像记得有段时间它影响了git commit -a也很糟糕,但现在好多了。 (我不确定哪些 Git 版本表现不佳-a.)

Long

Git 使每个新的提交都来自——或the,在大多数情况下——索引。索引或任何索引本质上是建议的提交:它由一种扁平树组成,带有 blob 哈希值和文件名。它的形式特别方便git mktree,它将索引变成一系列tree对象并返回顶级树对象的哈希 ID,然后该对象将进入提交对象。

那么,问题涉及这三个部分:

  1. 恰恰which索引被用来构建新的提交?
  2. 那个索引可以修改吗?如果是这样,新的提交会发生什么?
  3. 这有何影响the index?

Here, the索引是与工作树一起使用的特殊的、区分的索引。每个工作树有一个这样的索引:如果您使用git worktree add你会得到更多的工作树,并且每个工作树都有自己的私有索引,但你只能in一次一个工作树,所以“这个工作树的索引”是the index.

然而,当你跑步时git commit,你可以指示它(使用--only和/或其他命令行参数)来构建自己的private索引,与the指数。如果您这样做了,它将使用环境变量运行每个不同的钩子,GIT_INDEX_FILE,设置为临时索引的路径名。 (如果不,GIT_INDEX_FILE将包含.git/index,这是通往the索引文件。)

所以问题1的答案是:$GIT_INDEX_FILE.

现在,您实际上可以修改 Git 用于构建提交的索引,因为 Git 会在运行钩子后重新读取该索引。所以问题 2 的答案是:是的,这使得下一次提交使用正在使用的索引中的任何内容。

Q3是最难的。如果你使用git commit --only <paths>,Git 必须创建一个临时索引:

  • 是一个副本HEAD
  • 除指定的<paths>

不打扰the根本没有索引。但是,如果提交继续并成功,Git 现在必须修改the索引来说明这些事实<paths>新的中有新的斑点HEAD commit.

事实上,Git 需要使two临时索引(索引?),一个用于建议的提交及其--only文件,一个用于建议的提交结果。提议的提交结果变为index.lock,充当新索引。

If you git add文件运行时,它们将进入临时索引。但是关于the指数?让我们来了解一下:

$ cat .git/hooks/pre-commit
#! /bin/sh
echo pre-commit hook, GIT_INDEX_FILE = $GIT_INDEX_FILE
git add sneaky
$ echo this is the base version of sneaky > sneaky
$ echo this is the base version of other > other
$ git add other sneaky
$ git commit -m 'create two files'
pre-commit hook, GIT_INDEX_FILE = .git/index
[master 5131b63] create two files
 2 files changed, 2 insertions(+)
 create mode 100644 other
 create mode 100644 sneaky

如您所见,预提交挂钩在此处触发,并添加sneaky。这没什么大不了的,因为这次提交复制到索引中的内容是the索引 - 已经是相同的基本版本。

但是现在,让我们修改当前的内容sneaky, git add它,并修改当前内容other, and git add它,这样我们就有了新的内容the两个文件的索引...

$ echo version 2 of other > other
$ echo version 2 of sneaky > sneaky
$ git add other sneaky

此时,索引和工作树都有“版本2”。现在让我们将两个工作树文件更新为“版本 3”without git add荷兰国际集团他们:

$ echo version 3 of other > other
$ echo version 3 of sneaky > sneaky
$ git status --short
MM other
MM sneaky

这告诉我们,HEAD、索引和工作树版本都不同:HEAD每个版本都是基础版本,索引版本是版本 2,工作树版本是版本 3。

现在我们运行git commit --only other:

$ git commit --only other -m 'jump other straight to v3'
pre-commit hook, GIT_INDEX_FILE = [path]/.git/next-index-72393.lock
[master 91ec03b] jump other straight to v3
 2 files changed, 2 insertions(+), 2 deletions(-)

现在让我们看看提交、索引和工作树中有什么:

$ git status --short
MM sneaky

好的,工作树版本other匹配索引版本other哪个匹配HEAD的版本other, so:

$ cat other
version 3 of other

它们都是版本 3。那又如何呢?sneaky, 尽管?这HEAD和索引不同,索引和工作树也不同。让我们看看里面有什么HEAD first:

$ git show HEAD:sneaky
version 3 of sneaky

现在让我们看看工作树中有什么:

$ cat sneaky
version 3 of sneaky

啊哈,这些很匹配!棘手的部分是查看索引版本,但我们也可以这样做git show:

$ git show :0:sneaky
version 2 of sneaky

哇,看看那个!The索引版本是旧版本!

那么,这就是问题 3 的答案:git add在预提交挂钩中更新用于构建下一个提交的索引,但如果这是一个暂时的索引,它does not更新将成为真实索引的内容。这可以说是一个错误:git add在预提交挂钩中还应该添加到将成为的索引the指数。实现这一点有点棘手(git commit也许可以在挂钩之前和之后读取临时索引并将任何更新复制到index.lock文件)。

请注意,我跳过了如果您在没有提交的情况下提交会发生什么的详细信息--only。幸运的是,在这种情况下,您添加到的索引是the索引,所以一切都按您的预期进行:

$ git reset --hard 5131b63
HEAD is now at 5131b63 create two files
$ echo v2 > other && echo v2 > sneaky && git add other
$ git commit -m 'regular commit'
pre-commit hook, GIT_INDEX_FILE = .git/index
[master 10a8b20] regular commit
 2 files changed, 2 insertions(+), 2 deletions(-)
$ git status --short
$ 

预提交git add替换了索引版本sneaky,并且它保持被替换......即使提交它也会被替换fails.

另请注意,使用时git commit -a,我们得到一个不同的临时索引:

$ git commit -a -m test
pre-commit hook, GIT_INDEX_FILE = [path]/.git/index.lock

在这里,Git 的用途git commit -a是创建建议的新索引as the index.lock文件。这git add正常进行,按照通常的方式添加文件,然后当提交成功时,Gitrenames index.lock to index。这会解锁索引文件,同时将修改后的索引放在适当的位置,以便答案git commit -a到Q3就是临时索引变成了索引。这与对于git commit --only.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可以在预提交 git hook 中重新暂存文件吗? 的相关文章

  • 我可以从命令行向 github 添加问题吗?

    我是 git 新手 我希望能够通过 github 绘制我的项目的计划和进度 问题是 这需要在 github com 上使用浏览器进行大量点击 并且我希望能够通过使用命令行程序来自动执行该任务 github 有命令行界面吗 有一个ghi ge
  • 如何在 PowerShell 中键入 TAB 字符?

    Task 默认情况下 在 Windows 命令提示符中按 TAB 键将输出文件名 而在 PowerShell 中则不会执行任何操作 我希望能够在交互模式下键入 TAB 字符 而不是通过脚本 Research 我在这个网站上和通过谷歌搜索发现
  • 向后台进程发送命令

    我有一个先前运行的进程 process1 sh 它正在后台运行 PID 为 1111 或其他任意数字 我怎样才能发送类似的东西command option1 option2PID 为 1111 的进程 I don t想要启动一个新的proc
  • 如何根据 Bash 中的 VI 模式更改光标形状?

    我的 bashrc 中有以下行 set o vi 我希望我的光标在插入模式下具有管道形状 在命令模式下具有块形状 就像我在 vimrc 中放置以下内容时在 Vim 中的形状一样 let t SI e 6 q let t SR e 4 q l
  • 在 git 提交消息中使用任何 utf-8 字符是否安全?

    我发现使用 UTF8 字符 例如 很有用 请参阅here http www utf8icons com subsets dingbats 在提交消息中 重构 NewService 添加了更好的服务 OldServiceA 据我所见 它see
  • git 克隆错误:致命:git upload-pack:由于远程端可能的存储库损坏而中止

    我对 git 存储库具有读 写访问权限 但是当我尝试 git clone 时 出现以下错误 x ubuntu temp git clone email protected cdn cgi l email protection Corp ap
  • 有关多个远程存储库的 Git 状态

    我有一个脚本 如果我忘记在 40 多个存储库中提交或推送一些代码 它会通过电子邮件向我发送提醒 在我的两个项目中 我遵循了这些帖子中的答案 其中我设置了 git push 来推送到多个存储库 从多个远程位置拉 推 https stackov
  • 如何让 git 和 copSSH 在正确的目录中查找密钥?

    我刚刚安装了 Windows 版 copSSH 当我启动它时 我得到一个目录C copSSH home Nick ssh其中有我的酒吧和私钥 当我通过 Cygwin bash 窗口访问此目录时 使用 ssh 用户 主机 我很高兴地登录了 但
  • “git add”返回“致命:外部存储库”错误

    我刚刚进入 git 的奇妙世界 我必须提交我对程序所做的一系列更改 位于名为的目录中 var www myapp 我创建了一个新目录 home mylogin gitclone 从这个目录中 我做了一个git clone针对公共回购 我能够
  • “Connect-MsolService”未被识别为 cmdlet 的名称

    PSCommand commandToRun new PSCommand commandToRun AddCommand Connect MsolService commandToRun AddParameter Credential ne
  • git for-each-ref - 按年龄过滤结果

    我正在使用以下命令here https stackoverflow com a 39251131 5812876 git for each ref format color cyan authordate format m d Y I M
  • 本地git,推送到tfs远程repo

    我厌倦了向我的队友解释使用 DVCS 相对于 CVCS 的好处 他们中的一些人害怕学习曲线 另一些人则看不出任何原因 因为对他们来说 这都是一样的 就我个人而言 我对 TFS 及其问题感到非常厌倦 每当我需要进行一些小的 修复 时 我都必须
  • 在 GitHub 上执行拉取请求时避免不需要的合并提交和其他提交

    我在 Github 上分叉了一个项目 令远程上游为upstream我的远程存储库是origin 我当地的master分支设置为跟踪远程master分支 然后我在本地添加了一些东西master 时不时与上游汇合 直到今天我想发出pull re
  • 如何在本地快速拉取拉取请求

    在合并拉取请求之前 我想在本地快速拉取请求并运行测试并测试一些内容 我还不想点击 gihub 合并拉取请求 我以为滑轮会有帮助http ejohn org blog pulley http ejohn org blog pulley 但我收
  • Git 中的合并冲突是由什么构成的?

    git 如何确定特定合并存在冲突以及冲突是什么 我的猜测是这样的 如果正在合并的两个提交有一个共同的父提交 并且如果它们都更改了父提交的 X 行 那就是冲突 让我的理解变得复杂的是 更改 X 行 可能意味着用几行新行替换它 但这仍然显示为一
  • 使用 shell=True 将 PATH 设置为 bitbake 的“source”在 Python 中没有效果

    下面是shell脚本中的代码 source proj common tools repo etc profile d repo sh repo project init branch repo project sync source pok
  • Bash 中所有匹配的^单词^替换^?

    为了澄清 我正在寻找一种方法来执行global搜索并替换先前使用的命令 word replacement 似乎只替换了第一场比赛 有没有一些set我无法选择的选项 尝试这个 echo oneone oneone gs one two Rep
  • 将 JSON 导出到环境变量

    如果我有这样的 JSON hello1 world1 testk testv 我想将每个键值对导出为环境变量 如何通过 shell 脚本来做到这一点 例如 当我在终端上写时 echo hello1 world1应该打印其他键值对吗 注意 上
  • 如何通过哈希显示提交的日期和时间

    I used git reflog识别我创建特定分支时的哈希值 我得到了哈希值fe1ddcdef 我还没有将此分支推送到远程 我现在正在尝试查找日期和时间fe1ddcdef发生 git reflog只告诉我 fe1ddcdef HEAD 1
  • 如何查看 github 的 SSH 密钥?

    我最近收到一封来自 Github 的电子邮件 要求我检查我的 SSH 密钥 请检查您的钥匙并确保您 认出他们 如果您有任何疑问 请拒绝钥匙并 上传新密钥 如何在 ubuntu 11 10 上使用 git 检查我的密钥 您可以按照 GitHu

随机推荐