“git update-index --assume-unchanged file”实际上将这些信息保存到哪里?

时间:2011-08-18 22:41:14

标签: git git-index

我喜欢直接修改配置文件(比如.gitignore和.git / config)而不是记住任意命令,但我不知道Git在哪里存储传递给“git update-index --assume”的文件引用-unchanged file“。

如果你知道,请告诉我们!

2 个答案:

答案 0 :(得分:4)

它说命令中的位置 - git update-index

因此,您无法真正编辑索引,因为它不是文本文件。

另外,要详细了解git update-index --assume-unchanged命令存储的内容,请参阅Using “assume unchanged” bit section in the manual

答案 1 :(得分:2)

正如其他人所说,它存储在索引中,该索引位于.git/index

经过一些侦探工作,我发现它位于每个索引条目的assume valid位。

因此,在理解后面的内容之前,您应首先了解索引的全局格式,如my other answer中所述。

接下来,我将解释我如何验证"假设有效"比特是罪魁祸首:

  • 凭经验
  • 阅读消息来源

实证

hd的时间。

设定:

git init
echo a > b
git add b

然后:

hd .git/index

给出:

00000000  44 49 52 43 00 00 00 02  00 00 00 01 54 e9 b6 f3  |DIRC........T...|
00000010  2d 4f e1 2f 54 e9 b6 f3  2d 4f e1 2f 00 00 08 05  |-O./T...-O./....|
00000020  00 de 32 ff 00 00 81 a4  00 00 03 e8 00 00 03 e8  |..2.............|
00000030  00 00 00 00 e6 9d e2 9b  b2 d1 d6 43 4b 8b 29 ae  |...........CK.).|
00000040  77 5a d8 c2 e4 8c 53 91  00 01 62 00 c9 a2 4b c1  |wZ....S...b...K.|
00000050  23 00 1e 32 53 3c 51 5d  d5 cb 1a b4 43 18 ad 8c  |#..2S<Q]....C...|
00000060

现在:

git update-index --assume-unchanged b
hd .git/index

给出:

00000000  44 49 52 43 00 00 00 02  00 00 00 01 54 e9 b6 f3  |DIRC........T...|
00000010  2d 4f e1 2f 54 e9 b6 f3  2d 4f e1 2f 00 00 08 05  |-O./T...-O./....|
00000020  00 de 32 ff 00 00 81 a4  00 00 03 e8 00 00 03 e8  |..2.............|
00000030  00 00 00 00 e6 9d e2 9b  b2 d1 d6 43 4b 8b 29 ae  |...........CK.).|
00000040  77 5a d8 c2 e4 8c 53 91  80 01 62 00 17 08 a8 58  |wZ....S...b....X|
00000050  f7 c5 b3 e1 7d 47 ac a2  88 d9 66 c7 5c 2f 74 d7  |....}G....f.\/t.|
00000060

通过比较两个索引并查看the global structure of the index,可以看到唯一的区别是:

  • 字节数0x48(第40行第9位)从00更改为80是我们的标志,是缓存条目标志的第一位。
  • 0x4C0x5F的20个字节。这是预期的,因为它是整个索引的SHA-1。

虽然我也知道从0x340x47的索引条目的SHA-1不考虑标志,因为它在两个索引之间没有变化。这可能就是为什么标志放在SHA之后,只考虑它之前的标志。

源代码

现在让我们看看它是否与Git 2.3的源代码一致。

首先查看update-index的来源,grep assume-unchanged

这会导致the following line

{OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL,
  N_("mark files as \"not changing\""),
  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG},
{OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL,
  N_("clear assumed-unchanged bit"),
  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG},

因此值存储在mark_valid_only。 Grep它,发现它只用at one place

if (mark_valid_only) {
  if (mark_ce_flags(path, CE_VALID, mark_valid_only == MARK_FLAG))
    die("Unable to mark file %s", path);
  return;
}

CE表示缓存条目。

通过快速检查mark_ce_flags,我们看到了:

if (mark)
  active_cache[pos]->ce_flags |= flag;
else
  active_cache[pos]->ce_flags &= ~flag;

因此该函数基本上设置或取消设置CE_VALID位,具体取决于mark_valid_only,这是一个三态:

  • 标记:--assume-unchanged
  • unmark:--no-assume-unchanged
  • 不执行任何操作:0
  • 设置的选项的默认值{OPTION_SET_INT, 0

接下来,通过在builtin/下点击,我们发现没有其他地方设置CE_VALID的值,因此--assume-unchanged必须是设置它的唯一命令。

然而,该标志在源代码的许多地方使用,应该是预期的,因为它有许多副作用,并且每次都使用它,如:

ce->ce_flags & CE_VALID

所以我们得出结论,它是struct cache_entryce_flags字段的一部分。

索引在cache.h指定,因为它的一个功能是用于更快地创建提交的缓存。

通过查看cache.h下的CE_VALID及其周围行的定义:

#define CE_STAGEMASK (0x3000)
#define CE_EXTENDED (0x4000)
#define CE_VALID (0x8000)
#define CE_STAGESHIFT 12

因此我们得出结论,它是整数(0x8000)的第一位,紧挨CE_EXTENDED,与my earlier experiment一致。