- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以我的经验,git commit -a
具有与git commit .
相同的行为,但是,最近,我创建了一个pre-commit钩子,该钩子会自动格式化我的源代码,现在git commit .
具有一些意外的副作用:提交的文件最终结束了在commit命令完成后,在工作目录和索引中进行修改。 git commit -a
不会发生这种情况。我试图了解运行git commit .
时幕后发生的情况,这是导致这种情况发生的原因,并查看是否存在在预提交的钩子脚本中正确处理该问题的方法。
预提交钩子:
git_toplevel=$(git rev-parse --show-toplevel)
git --no-pager diff -z --cached --name-only --diff-filter=ACMRT | $git_toplevel/meta/reformat.bash -s files
git --no-pager diff -z --name-only --diff-filter=ACMRT | xargs -0 --no-run-if-empty git add
[]$ git status
# On branch eroller/format-clean-filter
# Your branch is ahead of 'origin/eroller/format-clean-filter' by 1 commit.
# (use "git push" to publish your local commits)
#
# 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/host/cnv/denovo/denovo_cnv.cpp
#
no changes added to commit (use "git add" and/or "git commit -a")
[]$ git diff
diff --git a/src/host/cnv/denovo/denovo_cnv.cpp b/src/host/cnv/denovo/denovo_cnv.cpp
index 7cfb8dc..14058e3 100644
--- a/src/host/cnv/denovo/denovo_cnv.cpp
+++ b/src/host/cnv/denovo/denovo_cnv.cpp
@@ -28,7 +28,7 @@ using namespace std;
namespace cnv {
namespace denovo {
-SegmentsBySample LoadCallsForSamples(const vector<string>& callFiles, const ReferenceDictionary& reference)
+ SegmentsBySample LoadCallsForSamples(const vector<string>& callFiles, const ReferenceDictionary& reference)
{
function<SegmentsBySample::value_type(const string&)> loadCalls = [&](string callFile) {
return LoadCalls(callFile, reference);
[]$ git commit -m 'test' .
[]$ git status
# On branch eroller/format-clean-filter
# Your branch is ahead of 'origin/eroller/format-clean-filter' by 2 commits.
# (use "git push" to publish your local commits)
#
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: src/host/cnv/denovo/denovo_cnv.cpp
#
# 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/host/cnv/denovo/denovo_cnv.cpp
#
[]$ git diff
diff --git a/src/host/cnv/denovo/denovo_cnv.cpp b/src/host/cnv/denovo/denovo_cnv.cpp
index 14058e3..7cfb8dc 100644
--- a/src/host/cnv/denovo/denovo_cnv.cpp
+++ b/src/host/cnv/denovo/denovo_cnv.cpp
@@ -28,7 +28,7 @@ using namespace std;
namespace cnv {
namespace denovo {
- SegmentsBySample LoadCallsForSamples(const vector<string>& callFiles, const ReferenceDictionary& reference)
+SegmentsBySample LoadCallsForSamples(const vector<string>& callFiles, const ReferenceDictionary& reference)
{
function<SegmentsBySample::value_type(const string&)> loadCalls = [&](string callFile) {
return LoadCalls(callFile, reference);
[]$ git diff --cached
diff --git a/src/host/cnv/denovo/denovo_cnv.cpp b/src/host/cnv/denovo/denovo_cnv.cpp
index 7cfb8dc..14058e3 100644
--- a/src/host/cnv/denovo/denovo_cnv.cpp
+++ b/src/host/cnv/denovo/denovo_cnv.cpp
@@ -28,7 +28,7 @@ using namespace std;
namespace cnv {
namespace denovo {
-SegmentsBySample LoadCallsForSamples(const vector<string>& callFiles, const ReferenceDictionary& reference)
+ SegmentsBySample LoadCallsForSamples(const vector<string>& callFiles, const ReferenceDictionary& reference)
{
function<SegmentsBySample::value_type(const string&)> loadCalls = [&](string callFile) {
return LoadCalls(callFile, reference);
git commit .
或
git commit [--only] -- <files>
,我决定在预提交挂钩中给出错误。这是我的预提交脚本中的检查内容:
if [[ $GIT_INDEX_FILE != *"/index" ]] && [[ $GIT_INDEX_FILE != *"/index.lock" ]] ; then
echo "Error: pre-commit reformatting using unsupported index file ($GIT_INDEX_FILE)." >&2
echo " Are you using 'git commit [--only] -- <files>' to bypass staging?" >&2
echo " Use git commit -a or stage your files before committing using git add -- <files>" >&2
echo " Use '--no-verify' to bypass reformatting (not recommended)" >&2
exit 1
fi
最佳答案
这里的根本问题是,Git并不是从工作树而是从索引进行提交,这就是为什么首先需要git add
文件的原因-但是索引是一种白色谎言,因为可以有更多的谎言索引文件不仅仅是一种标准文件。 (该索引也称为暂存区域或缓存,具体取决于Git的哪一部分正在执行调用。)
索引(我指的是一个标准索引)是.git
中名为index
的文件。如果检查您的.git
目录,则会找到这样的文件。过去,实际上只有一个文件。在现代Git(2.5或更高版本)中,由于添加了工作树,因此画面变得更加模糊:实际上每个工作树只有一个索引文件,因此.git/index
只是主工作树的索引。每个工作树都有一个辅助索引-但这并不是我要表达的意思,这里,这只是一个例子,它显示了一个单一索引的假设已经在边缘发生了变化。诚然,您使用的是Git 1.8.3.1(确实很旧),但它也比简单的白色谎言“一个索引”设置更为复杂。
使用git commit -a
时,Git会创建一个新的额外索引。使用git commit .
时,您要调用git commit --only .
(see the documentation for details),Git会创建两个新的额外索引(索引?)。
Git的所有部分都能够重定向Git的其余部分以使用不同的非标准索引,并且git commit
的这些各种选项均使用此功能。请注意,git commit -a
等效于git commit --include
,后跟需要添加的任何文件的名称。真正棘手的情况是您正在使用的git commit --only
。
一旦开始增加索引文件,事情就会变得混乱!
请记住,索引本质上是建议的下一次提交。如果只有一个索引(对于这个工作树,如果我们正在谈论Git 2.5或更高版本),那么只有一个建议的下一次提交。不太困难,我们只需要考虑每个文件有三个副本即可。让我们选择一个文件,例如README.md
:HEAD:README.md
是README.md
的当前提交版本。您无法更改。 (您可以移动HEAD
本身,但是README.md
的已提交副本位于提交中,这是通过提交的哈希ID找到的,并且不会更改。)
名称HEAD:README.md
仅在Git内部有效。该名称访问该文件的冻结,经过Git验证,冻结干燥的副本;此副本将永远不会改变。例如,您可以通过git show HEAD:README.md
看到它。:README.md
是索引中README.md
的副本。它最初与HEAD:README.md
相同,但是如果您运行git add README.md
,则现在可能有所不同。
名称:README.md
也仅在Git内部有效。该名称将访问此可替换但已Git认证(冻结干燥格式)的文件副本,该副本存储在索引中。您可以随时用git add
替换。
最后,README.md
是普通(非Git认证)文件。它不在Git中!它不在索引中!它在您的工作树中,您可以使用所有普通的计算机工具来查看和处理它。 Git确实不使用此文件,它只是覆盖它或在您签出其他提交时将其删除。除了使用git status
等进行检查之外,Git唯一要做的就是让您使用git add
将其复制回索引,覆盖之前的内容(并在过程中将其冻干)。
运行git status
运行两个git diff
:
第一个将HEAD
提交与索引进行比较,即当前提交中的内容与建议的下一次提交中的内容。此处列出的任何其他内容均已列为提交阶段。一切都一样,Git只是悄无声息。
第二个git diff
将索引与工作树进行比较,即提议的提交中包含什么,以及可以复制到索引中的内容。此处列出的所有其他内容均未列为未提交。同样,再次,Git悄无声息。
(然后是最后一步,检查工作树中根本不在索引中的文件。Git会抱怨这些,说它们是未跟踪的,除非您在.gitignore
中列出它们。在.gitignore
不会更改索引中是否存在该文件的副本,而只会更改Git是否发牢骚。)
当您运行git commit
时,除非您使用--only
,--include
或-a
,否则Git会打包索引中的所有内容,并使用它来进行新的提交。
指数out the wazoo
使用git commit --only
,Git可以创建三个索引文件:
一个是标准之一。一开始没有被改动。那是正常的.git/index
。
一个是该副本的副本,其中--only
文件已被git add
对其进行复制。有时在.git/index.lock
中。也许总是在这里!如果是这样,那将提供一种处理我在下面概述的情况的方法。但是没有文档可以保证这一点。
第三个是新的,首先提取HEAD
,然后git add
将--only
文件添加到其中。
如果在运行git add
之前没有任何git commit -a
内容,则第一个索引文件和第三个索引文件会匹配,因为将--only
文件添加到常规索引中的效果与从HEAD
创建新的临时索引并添加--only
文件。但是,否则所有三个文件可能都不同!
然后,Git从第三个索引进行新的提交。如果新的提交成功,则Git用第二个索引替换常规索引(此替换通过rename
系统调用发生)。否则,Git返回正常索引。 (请注意,工作树什么都没有发生。)
如果使用git commit --include
或git commit -a
,则Git仅增加一个索引,因此您具有:.git/index
中的标准索引,以及到目前为止添加的内容;和
临时文件中的一个额外索引:该索引从标准索引的副本开始,但是随后Git将列出的文件或其他修改的文件添加到该索引中。
然后,Git启动提交过程。如果一切顺利,完成Git后,Git将重命名临时索引,使其成为标准索引。如果情况不佳,Git会删除临时索引,而标准索引保持不变。同样,工作树没有任何反应。
介绍预提交挂钩
在准备任何额外的索引文件之后,Git会运行您的预提交钩子。特殊的环境变量$GIT_INDEX_FILE
为Git用来进行新提交的索引命名。因此,存在三种情况,其中两种情况还不错,而其中一种则很糟糕:
您正在执行常规提交。 GIT_INDEX_FILE
命名普通索引,一切正常。
您正在执行git commit --include
或git commit -a
,并且GIT_INDEX_FILE
命名第二个索引;没有第三索引;如果提交完成,Git将重命名第二个索引。
您正在执行git commit --only
,并且GIT_INDEX_FILE
命名第三个索引。找到第二个索引没有简单的方法,如果提交成功,第二个索引将在提交之后就位!
如果您选择对存储在索引中的文件进行更改,您的工作就是将它们更改为Git将用于提交的索引。为此,可以根据需要使用git add
,因为这会将文件从工作树复制到$GIT_INDEX_FILE
中命名的索引。
但是,第一个问题是您不能查看工作树中的文件。他们无关紧要!它们可能包含与索引中完全不同的内容。在git commit --only
期间尤其如此。
第二个更大的问题是,如果您更新了git commit --only
使用的第三个索引,则还应该更新git commit --only
使用的第二个索引。这部分很棘手,因为除了假定它在.git/index.lock
中之外,没有其他简单的方法可以找到它。尽管这可能会起作用,但在这里我不建议这样做。
我真的对此没有任何建议-您发现的任何偷偷摸摸的方法都可能会破坏,因为处理第三个索引的代码(当前的2.21 ish Git称为“假索引”)在1.8和现代Git之间已发生了很大变化。通常的最佳实践建议是根本不对Git挂钩进行任何特殊格式化。相反,让Git挂钩仅检查文件的索引副本是否格式正确:如果是,则继续提交,否则,放弃提交。其余的留给用户。
另一种选择
我已经看到和使用的替代方法是检查$GIT_INDEX_FILE
的实际设置。如果将其设置为.git/index
,则用户正在使用git commit
,而没有任何特殊设置。 this same pre-commit hook中的另一个技巧(调用clang-format和autopep8)是比较将被格式化的文件的索引和工作树,并在它们不匹配时拒绝运行。
关于git - 带有“git commit”的意外行为。预提交 Hook 修改暂存文件时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55582892/
我正在寻找一种方法来编写 Signed-off-by:当我提交时自动标记。 我尝试通过 .git/config 文件配置它 (Reference) .我把这些代码行: [alias] comm
我使用的是 visual studio 2013,在提交 C# 代码时我面临 3 个选项。我需要解释每个选项之间关于我的本地存储库与 GitHub 存储库发生的情况的差异。 选项 1 表示提交 选项
我刚从 classes12.jar 升级到新的 jdbc 驱动程序到 ojdbc7.jar 我的应用在使用 ojdbc7.jar 运行时抛出异常: java.sql.SQLException: Cou
我问的是 Oracle SQL*PLUS ... 最佳答案 没有 :-) Oracle says The WORK keyword is supported for compliance with s
我必须在许多分支、许多存储库上恢复对文件所做的更改。我知道我可以使用 git checkout 哈希文件名,然后推送该更改。 问题是,我只知道在我想要恢复的实际提交之前有两次提交。 我怎样才能在这之前
看起来很简单,但我就是不明白。我在我的应用程序的根目录中。 这是我的工作流程。 git add . git commit -m "added a new feature some files chan
假设我有一个 git 分支,在共享它之前的最后审查中,我发现了一些小错误,例如拼写错误。我想做的是将那个补丁应用为“修复”,但它实际上会影响许多提交,因此在最终历史记录中没有错误的迹象。 也就是说,如
当我运行hg commit时,Mercurial会为我的提交消息生成一个文件,如下所示: HG: Enter commit message. Lines beginning with 'HG:' a
我已经为项目创建了一个新的存储库,并向其中添加了一些现有的代码库 (llvm)。该代码库大约有 18,000 个文件,这使得我的初始提交花费了大量时间。 (阅读5小时) 有没有办法将这个巨大的提交分成
我在 git review 上得到以下内容: git review You are about to submit multiple commits. This is expected if you
我一直在寻找一种替代解决方案来压缩分支中的一系列提交。我过去所做的是使用 git rebase -i HEAD~然后选择哪个 promise 进行压缩。通常我 pick编辑最新的提交,并压缩其间的冗余
把玩Git和GitHub,我发现有时候一个 git commit -a 需要提交修改过的文件。 (此文件已添加到项目中)。 但有时候,只是一个 git commit 会起作用。如果使用 Mercuri
我正在努力思考 Git 的复杂性。 我使用“git clone [url here]”从 GitHub 下载了一个存储库。 我做了一些更改,尝试使用“git commit”提交它们。这似乎没有将更改推
当试图恢复到之前的提交时,我尝试了: git revert --no-commit 0766c053..HEAD 然而这给出了一个错误: empty commit set passed 问题错误是什么
我的存储库的历史非常复杂。我经常发现自己想知道过去的某个提交是“在”还是“可从”某个修订版(通常是我的一个头脑)“进入”或“可访问” 我该怎么做呢? 最佳答案 您可以使用 revsets syntax
我有:http://windows.github.com/ 我当前的项目有大约 20k 个文件,大约 150MB(并且不说它有多慢而且我现在什么也做不了)它甚至不允许我提交!我收到此错误:提交失败:无
我正在运行 postgres 9.2 服务器并有一个使用 psycopg 2.5 的 python 客户端。 我进行了一些测试,因为我在日志文件中遇到了很多警告:没有正在进行的事务条目。 我有一些代码
我的主要问题是总是执行 git commit -am 而不是 git add 是否有意义。然后是 git commit -m? 我知道 -am 表示它将添加修改后的 TRACKED 文件的所有更改。所
如果我想查看 之间的差异和工作目录 (WD),我运行 % git diff 这通常会做我想做的事,但如果 WD 包含在 时被跟踪的文件,它就会这样做。已创建,但现在(或在当前分支中)未被跟踪,则
我正在阅读有关 git 对象的信息:blob、树、提交、标签。为了更好地理解 git 的工作原理,我尝试了一些低级命令,如 write-tree 和 commit-tree。 mkdir 测试; cd
我是一名优秀的程序员,十分优秀!