실행할 수 있는 스크립트를 작성하고 싶습니다.
git diff --name-status master..<BRANCH>
하지만 내가 이것을 실행하면 :
for i in $(git branch | grep -v master); do
echo $i;
done
에코 별표 때문에 디렉토리가 에코됩니다 git branch
(현재 디렉토리에 디렉토리가 있습니다).
* <SELECTED BRANCH>
*
확장되는 이유와 이를 방지하는 방법은 무엇 입니까?
고쳐 쓰다: 다음을 사용하여 이를 방지할 수 있습니다.
for i in $(git branch | tr -d '*' | grep -v master);
done;
그런데 왜 이런 일이 발생합니까? 별표를 제거해야 하는 이유는 무엇입니까?
답변1
따옴표가 없는 변수 및 명령 대체(예: $i
또는 $(git …)
적용)분할+전역 연산자문자열 결과에. 그건:
- 변수 값이나 명령 출력을 포함하는 문자열을 구성합니다(후자의 경우 마지막 줄 바꿈 제외).
- 값에 따라 문자열을 별도의 필드로 분할
IFS
. - 각 필드를 와일드카드 패턴으로 해석하고 이를 일치하는 파일 이름 목록으로 바꿉니다. 패턴이 일치하는 파일이 없으면 그대로 둡니다.
git branch | grep -v master
출력 내용(1단계)은 * master
두 개의 필드로 분할(2단계) *
되고 (3단계) 현재 디렉터리의 파일 이름 목록 master
으로 대체됩니다.*
와일드카드를 일시적으로 비활성화하기 위해 실행할 수 있습니다 set -f
. 또 다른 접근 방식은 명령 대체를 피하고 대신입력 구문 분석read
. 하지만 어느 쪽도 옳은 일이 아닙니다. git 출력에 필요한 것보다 더 많은 내용이 포함되어 있기 때문에 가짜 분기 이름을 얻게 됩니다( *
현재 분기를 나타내는 플래그뿐만 아니라 remotes/somewhere/foo -> bar
원격 추적 분기와 같은 것들도 포함). 우아하지 않더라도 다음은 안전하다고 생각합니다.
for i in $(git branch | sed -e 's/^..//' -e 's/ .*//'); do
echo $i
done
가장 믿을만한 방법은 다음과 같습니다.git-for-each-ref
.
for i in $(git for-each-ref --format='%(refname:short)' refs/heads refs/remotes); do
echo $i
done
답변2
while
이와 같은 텍스트 스트림은 루프 대신 루프를 사용하여 읽어야 합니다 .for
, 이로 인해 문제가 발생할 수 있습니다(재현할 수는 없지만). 이를 수행하는 간단한 방법은 다음과 같습니다.
git branch | while IFS= read -r line
do
echo "${line:2}"
done
비교하다:
$ cd -- "$(mktemp -d)"
$ git init
Initialized empty Git repository in /tmp/tmp.MJFmu7q7EH/.git/
$ touch README
$ git commit --allow-empty -m "Initial commit"
[master (root-commit) da46b03] Initial commit
$ git branch foo
$ git branch
foo
* master
$ for i in $(git branch)
> do
> echo $i
> done
foo
*
master
$ git branch | while IFS= read -r line
> do
> echo "${line:2}"
> done
foo
master