Gitの内部動作を学ぶために、以下のようにコミットハッシュを手動で計算したいと思います。これだから答えてください。
ただし、printf
動作中(以下を参照)、echo
コマンドの置き換え前にスペースを出力する奇妙な動作が発生します。
echo
Putが出力にこれらのスペースを含めるのはなぜですか?
間違ったこと(echo
):
$ (echo -ne "commit $(git cat-file commit cc540cb | wc -c)\0"; git cat-file commit cc540cb) | hexdump -Cv
00000000 63 6f 6d 6d 69 74 20 20 20 20 20 20 32 31 38 00 |commit 218.|
00000010 74 72 65 65 20 34 35 64 38 62 30 35 38 32 65 32 |tree 45d8b0582e2|
00000020 34 62 39 61 66 66 38 62 34 64 34 65 35 66 33 31 |4b9aff8b4d4e5f31|
00000030 65 35 38 64 62 38 37 38 61 33 64 32 35 0a 70 61 |e58db878a3d25.pa|
00000040 72 65 6e 74 20 64 64 31 37 31 64 61 35 62 61 64 |rent dd171da5bad|
00000050 31 34 62 36 30 37 36 65 64 64 36 30 66 35 38 33 |14b6076edd60f583|
00000060 33 63 39 33 63 65 38 33 61 36 66 64 61 0a 61 75 |3c93ce83a6fda.au|
00000070 74 68 6f 72 20 6e 6c 79 6b 6b 65 69 20 3c 6e 6c |thor nlykkei <nl|
00000080 79 6b 6b 65 69 40 67 6d 61 69 6c 2e 63 6f 6d 3e |[email protected]>|
00000090 20 31 35 38 36 37 30 33 39 31 39 20 2b 30 32 30 | 1586703919 +020|
000000a0 30 0a 63 6f 6d 6d 69 74 74 65 72 20 6e 6c 79 6b |0.committer nlyk|
000000b0 6b 65 69 20 3c 6e 6c 79 6b 6b 65 69 40 67 6d 61 |kei <nlykkei@gma|
000000c0 69 6c 2e 63 6f 6d 3e 20 31 35 38 36 37 30 37 34 |il.com> 15867074|
000000d0 35 38 20 2b 30 32 30 30 0a 0a 41 77 65 73 6f 6d |58 +0200..Awesom|
000000e0 65 20 72 65 62 61 73 65 21 0a |e rebase!.|
000000ea
正しい( printf
):
$ (printf "commit %s\0" $(git cat-file commit cc540cb | wc -c); git cat-file commit cc540cb) | hexdump -Cv
00000000 63 6f 6d 6d 69 74 20 32 31 38 00 74 72 65 65 20 |commit 218.tree |
00000010 34 35 64 38 62 30 35 38 32 65 32 34 62 39 61 66 |45d8b0582e24b9af|
00000020 66 38 62 34 64 34 65 35 66 33 31 65 35 38 64 62 |f8b4d4e5f31e58db|
00000030 38 37 38 61 33 64 32 35 0a 70 61 72 65 6e 74 20 |878a3d25.parent |
00000040 64 64 31 37 31 64 61 35 62 61 64 31 34 62 36 30 |dd171da5bad14b60|
00000050 37 36 65 64 64 36 30 66 35 38 33 33 63 39 33 63 |76edd60f5833c93c|
00000060 65 38 33 61 36 66 64 61 0a 61 75 74 68 6f 72 20 |e83a6fda.author |
00000070 6e 6c 79 6b 6b 65 69 20 3c 6e 6c 79 6b 6b 65 69 |nlykkei <nlykkei|
00000080 40 67 6d 61 69 6c 2e 63 6f 6d 3e 20 31 35 38 36 |@gmail.com> 1586|
00000090 37 30 33 39 31 39 20 2b 30 32 30 30 0a 63 6f 6d |703919 +0200.com|
000000a0 6d 69 74 74 65 72 20 6e 6c 79 6b 6b 65 69 20 3c |mitter nlykkei <|
000000b0 6e 6c 79 6b 6b 65 69 40 67 6d 61 69 6c 2e 63 6f |[email protected]|
000000c0 6d 3e 20 31 35 38 36 37 30 37 34 35 38 20 2b 30 |m> 1586707458 +0|
000000d0 32 30 30 0a 0a 41 77 65 73 6f 6d 65 20 72 65 62 |200..Awesome reb|
000000e0 61 73 65 21 0a |ase!.|
000000e5
答え1
wc -c
数字の前の空白出力:
$ wc -c <file
6
最初のコマンドでは、文字列とcommit
出力はwc -c
二重引用符で囲まれた文字列に格納されます。
2番目のコマンドでは、の出力はwc -c
引用符なしで使用されます。
引用符のないコンテキストでは、シェルは$IFS
結果の単語を使用する前に出力を文字(スペースを含む)に分割します。 (また、ファイル名の単語をグローブしますが、ここでは重要ではありません。)
コマンド置換を引用すると、2番目のコマンドと同じ出力が得られます。
2番目のコマンドが「正しい」と思っても、printf
コマンドの置き換えを引用しないのは、通常、シェルが分割とグロービングを実行するために悪い考えです。
コマンド置換を引用して(常に良い習慣であるため)、次の出力からスペースを明示的に削除することをお勧めしますwc -c
。
(printf "commit %s\0" "$(git cat-file commit cc540cb | wc -c | tr -d ' ')"; git cat-file commit cc540cb) | hexdump -Cv