简体   繁体   English

我如何使用git只在一个文件中提交一行用于提交,所有这些都来自脚本?

[英]How can I use git to stage only one line in a file for commit, all from a script?

I'm writing a simple pre-commit git hook that updates the year in copyright headers for files that are staged for commit. 我正在编写一个简单的预提交git钩子,用于更新提交的文件的版权标题中的年份。

After modifying the line with the copyright, I would like the hook to stage that line so that it is part of the commit. 在修改了具有版权的行之后,我希望钩子能够对该行进行分段,以使其成为提交的一部分。 It can't just git add the whole file, because there may be other pre-existing changes in there that shouldn't be staged. 它不能只是git add整个文件,因为可能还有其他预先存在的更改,不应该暂存。

I don't see any options in the git add manual the let you stage specific lines. 我没有看到git add手册中的任何选项让你登台特定的行。

I figure I could git stash save --keep-index , apply my change, git add the file, and then git stash pop , but that seems rather crude. 我想我可以git stash save --keep-index ,应用我的更改, git add文件,然后git stash pop ,但这看起来相当粗糙。 Any better approaches? 有更好的方法吗?

Here's another possible solution: 这是另一种可能的解决方案:

  1. Before running your copyright-modification script, do a git status to get a list of the files it's about to commit. 在运行版权修改脚本之前,请执行git status以获取要提交的文件列表。 Save the list of files. 保存文件列表。 Do a commit. 做一个提交。

  2. Then, stash the rest of the (unrelated) changes, and apply your script to the list of files saved above. 然后,隐藏其余的(不相关的)更改,并将您的脚本应用于上面保存的文件列表。 Use git commit --amend to change the previous commit. 使用git commit --amend更改先前的提交。

  3. Finally, pop the stash to restore your index. 最后,弹出存储以恢复索引。 Resolve conflicts if required. 如果需要,解决冲突。

I don't know of a way to tell git add to add only specific lines. 我不知道告诉git add add只添加特定行的方法。 How would you describe the lines to add? 你会如何描述要添加的行? By line number? 按行号? It seems that might be possible in a narrow set of circumstances, and not generally useful. 似乎在一小部分情况下可能是可能的,而且通常不是很有用。

You could patch the staged version of the file in a separate step, eg 您可以在单独的步骤中修补文件的分阶段版本,例如

blobid=$(git show :"$filepath" | copyright-filter | git hash-object -w --stdin)

if $? -eq 0; then

    git update-index --cacheinfo 100644 "$blobid" "$filepath" &&
    copyright-filter "$filepath"

fi

I've shamelessly assumed that your script is called copyright-filter and works as a filter or in place, depending on its arguments. 我无耻地假设您的脚本被称为copyright-filter并根据其参数作为过滤器或到位。

Looking at the source to git add --interactive it looks like the way it modifies the index is with git apply --cached . git add --interactive的源代码git add --interactive它看起来像修改索引的方式是使用git apply --cached Assuming your copyright is the first hunk of any diff, make the change and use: 假设您的版权是任何差异的第一部分,请进行更改并使用:

git diff -- file | 
awk 'second && /^@@/ {exit} /^@@/ {second=1} {print}' |
git apply --cached

Where that second line (the awk script grabs only the first diff hunk). 第二行( awk脚本只抓取第一个差异块)。 You could also construct the diff output by hand or use other rules to select the hunk. 您也可以手动构造diff输出或使用其他规则来选择hunk。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM