[英]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: 这是另一种可能的解决方案:
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. 做一个提交。
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
更改先前的提交。
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.