可以在预提交 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 中重新暂存文件吗? 的相关文章

  • 如何使用 Git 跟踪目录而不是文件?

    我最近开始使用 Git 但只有一件事遇到了麻烦 如何在不跟踪目录内容的情况下跟踪目录 例如 我正在开发的网站允许上传 我想跟踪上传目录 以便在分支等时创建它 但显然不是其中的文件 在开发分支中的测试文件或主控中的真实文件 在我的 gitig
  • PowerShell中有解析TOML文件的模块吗?

    我正在尝试寻找一个TOML https toml ioPowerShell 的文件解析器 我也找不到任何有关它的信息PowerShell 画廊 https www powershellgallery com 或在预安装的 PowerShel
  • Git 2.2.x 无缘无故更新旧包文件的时间戳

    Git 2 2 0 和 2 2 1 似乎修改了旧的时间戳 git objects pack pack pack偶尔会无缘无故地文件 它只是改变时间戳 内容是相同的 调试这一点很困难 因为它似乎很少进行更改 我在 2 2 0 之前的任何 Gi
  • Git difftool 未启动外部 DiffMerge 程序

    我一直遵循 戴夫的博客条目 http www davesquared net 2009 05 setting up git difftool on windows html 链接在此answer https stackoverflow co
  • 为所有子文件夹设置 git 配置值

    我知道可以设置每个存储库的配置来覆盖用户级配置 即 path to my repo gitconfig覆盖 gitconfig 是否可以设置 git 配置来覆盖给定文件夹的所有子文件夹的用户级设置 即 我有 topLevelFolder1
  • 如何在 Windows 下向 .sh 脚本传递参数?

    我正在尝试在 Windows 下执行 sh 脚本 我安装了 Git 它允许我执行 sh 文件 但是 如果不使用 sh 作为执行前缀 我似乎无法传递任何参数 我的 sh 文件 echo Test 1 如果我用以下命令执行它 gt sh tes
  • Git 到 TFS 源代码管理迁移

    我想看看 TFS 如何为我的命令工作 所以我想将我们当前的 GIT 存储库移动到 TFS 数据库 我们使用 GIT 来获得普遍的分支支持 因此我想使用 TFS 2010 来解决该问题 现在的问题是 如何将 GIT 存储库导出到 TFS 显然
  • 如何使用 GitHub GraphQL API 查看问题已在项目的列之间转移?

    我想确定卡片何时从一列移动到另一列GitHub 项目板 https help github com articles about project boards 使用 GitHub GraphQL API 我可以在项目板中列出所有问题 例如
  • 缺少节点-v59-linux-x64/grpc_node.node

    我正在尝试在我的服务器中使用 Firebase admin SDK 当我部署时 出现错误 我在 firebase admin node module 映射中缺少文件 node v59 linux x64 grpc node node 我在包
  • 当一组凭据下的计划任务启动的进程在另一组凭据下运行另一个程序时,Windows 是否有限制

    所以我有一个简单的例子 其中我有应用程序 A 它对用户 X 本地管理员 有一些硬编码的凭据 然后它使用硬编码的绝对路径启动带有这些凭据的应用程序 B A 和 B 以及 dotnet 控制台应用程序 但是它们不与控制台交互 只是将信息写入文件
  • Github - 上传文件

    我正在尝试将文件夹添加到 github 存储库 该文件在 github 上显示为空 并有一个绿色箭头 有谁知道如何解决这个问题 我将不胜感激你的帮助 谢谢 这看起来类似于 Git 如何跟踪未跟踪的内容 https stackoverflow
  • Git:从 master 以外的分支克隆

    我正在尝试从 Github 的存储库中提取数据 但我不想克隆主分支 我想克隆其他一些分支 当我尝试时git clone
  • 启动过程中的写入进度 - 等待

    我正在尝试创建安装脚本并在安装过程中显示进度条 localfolder Get Location path start process FilePath localfolder Installer exe ArgumentList sile
  • 显示 master 之前/之后有多少提交分支的别名

    新的 Bitbucket Branches 页面非常棒 它显示每个分支领先 落后于 master 的提交数量 是否有显示相同信息的 Git 别名 信息应显示 分店名称 上次更新是什么时候 其背后有多少提交 有多少提交领先于 master 看
  • 如何在 PowerShell 中从网络下载整个文件夹的文件/子文件夹

    我可以使用以下命令从网络下载单个文件 wc New Object System Net WebClient wc DownloadFile http blah root somefile ext C Downloads www blah r
  • Eclipse Git 关键字扩展

    每次我检查 git hub 服务器的源代码时 我都需要更新源代码修订关键字 version date 等 你可能知道 Git 中的主要问题是你无法使用以下命令修改文件 提交后有关提交的信息 因为 Git 首先对文件进行校验 基本上我想要实现
  • git 是否有任何静态接口?

    我一直在寻找一个宁静的 git api 但似乎没有找到 我得到的最接近的是 Github 的 api 来访问一些存储库信息 还有其他的实施吗 Orion Git API http wiki eclipse org Orion Server
  • Git 的企业采用率?

    最近一些同事之间进行了一场讨论 在当今的软件行业中 如何存在两个不同的世界 面向自由软件 公司的 Question Git 在企业环境中的使用情况如何 您在企业环境中使用 Git 的体验如何 无论如何 我们在工作场所使用 git 每个人都对
  • 部分共享git仓库

    我是 git 新手 我想知道是否支持以下场景 如果支持的话如何支持 即用于设置和更新的 git 命令 可以从三个不同的地方获取存储库 本地 镜像 和 github mirror 完全镜像 local github 镜像 local 但 受版
  • VSTS:在构建过期的情况下自动变基/合并和重新排队构建验证门

    我们最近对 PR 上的构建验证门进行了更改 这样 如果另一个提交在当前 PR 完成之前进入主分支 则构建会 立即 过期 看here https stackoverflow com questions 49418800 vsts invali

随机推荐