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
큰따옴표로 묶인 문자열 내에 보관됩니다.
두 번째 명령에서 출력은 wc -c
따옴표 없이 사용됩니다.
따옴표가 없는 컨텍스트에서 쉘은 $IFS
결과 단어를 사용하기 전에 공백을 포함하는 의 문자에 대한 출력을 분할합니다. (단어에 대한 파일 이름 글로빙도 수행하지만 여기서는 중요하지 않습니다.)
명령 대체를 인용하면 두 번째 명령에서도 동일한 출력을 얻게 됩니다.
두 번째 명령인 가 "올바르다"고 생각하더라도 printf
명령 대체를 인용하지 않는 것은 일반적으로 쉘이 수행하는 분할 및 글로빙으로 인해 나쁜 생각입니다.
명령 대체를 인용하는 것이 좋습니다(항상 좋은 습관이기 때문입니다). 대신 다음 출력에서 공백을 명시적으로 삭제합니다 wc -c
.
(printf "commit %s\0" "$(git cat-file commit cc540cb | wc -c | tr -d ' ')"; git cat-file commit cc540cb) | hexdump -Cv