Mercurial은 루트 디렉토리 (.hg가 포함 된)를 인쇄하는 방법을 통해
hg root
git에 .git 디렉토리가 들어있는 디렉토리를 얻는 것과 동등한 것이 있습니까?
bzr root
Bazaar에서 많이 사용되었습니다
Mercurial은 루트 디렉토리 (.hg가 포함 된)를 인쇄하는 방법을 통해
hg root
git에 .git 디렉토리가 들어있는 디렉토리를 얻는 것과 동등한 것이 있습니까?
bzr root
Bazaar에서 많이 사용되었습니다
답변:
예:
git rev-parse --show-toplevel
Git 명령을 더 직접 복제하려면 별명을 작성할 수 있습니다 .
git config --global alias.root 'rev-parse --show-toplevel'
이제 git root
처럼 작동 hg root
합니다.
참고 : 서브 모듈에서이 루트의 디렉토리가 표시됩니다 서브 모듈 과 없는 부모 저장소를. Git> = 2.13 이상을 사용하는 경우 하위 모듈이 수퍼 프로젝트의 루트 디렉토리를 표시 할 수 있는 방법이 있습니다. 자식이 그보다 오래된 경우 다른 답변을 참조하십시오.
git config --global alias.exec '!exec '
같은 것을 할 수 있도록 정의 git exec make
합니다. 쉘 별명은 항상 최상위 디렉토리에서 실행되기 때문에 작동합니다.
hg root
입니다. 체크 아웃 된 저장소의 최상위 디렉토리를 인쇄합니다. 그것은 당신에게 그것을 전환시키지 않습니다 (실제로 현재 디렉토리와 쉘의 전체 개념이 상호 작용하는 방식 때문에 그렇게 할 수 없었습니다).
~/my.proj/foo/bar
, 그리고 ~/my.proj
에 심볼릭 링크되어 ~/src/my.proj
, 위의 명령은 당신을 이동합니다 ~/src/my.proj
. 그 후에 원하는 것이 나무에 무관심하지 않으면 문제가 될 수 있습니다.
.git
디렉토리 안에있을 때 작동하지 않습니다 .
man
페이지 git-config
(아래의 별칭 ) 말합니다 :
별명 확장 앞에 느낌표가 있으면 쉘 명령으로 취급됩니다. [...] 쉘 명령은 저장소의 최상위 디렉토리에서 실행되며 반드시 현재 디렉토리 일 필요는 없습니다.
따라서 UNIX에서는 다음을 수행 할 수 있습니다.
git config --global --add alias.root '!pwd'
.zshrc
alias cg = "cd $ (git root)"을 정의하면 $ () 부분은 소스 타임에 평가되며 항상 z / sh 파일이있는 곳이므로 ~ / dotfiles를 가리 킵니다. .
했습니다 --show-toplevel
최근에 추가 된 git rev-parse
또는 왜 아무도 그것을 언급하지?
로부터 git rev-parse
매뉴얼 페이지
--show-toplevel
Show the absolute path of the top-level directory.
git-rev-parse
수정 사양 처리에 관한 이름으로 인해 추측하기가 어렵습니다 . BTW, 나는 다음 git --work-tree
과 유사한 작업 을 보게되어 기쁘다 git --exec-path[=<path>]
. 적어도 IMO는 그러한 기능을 찾는 것이 논리적 장소 일 것입니다.
root = rev-parse --show-toplevel
gitconfig에서 별칭 을 지정할 수 있습니다 .
git config --global alias.root "rev-parse --show-toplevel"
한 후 git root
작업 할 수있을 것입니다
git rev-parse --show-toplevel
는 하위 모듈에서 시도했을 때 작동합니다. git 서브 모듈의 루트 디렉토리를 출력합니다. 당신을 위해 무엇을 인쇄합니까?
--show-cdup
것으로 나타 --show-top-level
났습니다.
" git rev-parse --git-dir
"는 어떻습니까?
F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git
--git-dir
옵션이 작동하는 것 같다.
--git-dir
Show $GIT_DIR if defined else show the path to the .git directory.
이 git setup-sh
스크립트 에서 실제로 작동하는 것을 볼 수 있습니다 .
Git> = 2.13 인 하위 모듈 폴더에 있다면 다음을 사용하십시오 .
git rev-parse --show-superproject-working-tree
당신이 사용하는 경우 git rev-parse --show-toplevel
, 메이크업 확신이 망할 놈의 2.25+ (Q1 2020)가있다 .
.git
은 이미 루트 디렉토리에있는 경우 상대 경로를 제공하는 것으로 보입니다 . (적어도, 그것은 msysgit에서합니다.)
이미 최상위 레벨에 있거나 git 저장소에 없으면 cd $(git rev-parse --show-cdup)
집으로 데려다 줄 것입니다 (cd). cd ./$(git rev-parse --show-cdup)
그것을 고치는 한 가지 방법입니다.
cd "$(git rev-parse --show-cdup)"
. 이 기능은 cd ""
뒤로 돌아 가기보다 아무데도 걸리지 않기 때문에 작동합니다 $HOME
. 그리고 공백이있는 것을 출력 할 경우를 대비하여 $ () 호출을 인용하는 것이 가장 좋습니다 (이 경우이 명령은 그렇지 않습니다).
$PWD
. 이 예제는 $PWD
대신 git의 루트를 상대적으로 해결 realpath $PWD
합니다.
쉘 스크립트에서 사용하기 위해 현재 git root 디렉토리의 절대 경로를 계산하려면 readlink와 git rev-parse의 조합을 사용하십시오.
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdup
cwd에서 루트에 도달 할 수있는 올바른 수의 ".."또는 루트에있는 경우 빈 문자열을 제공합니다. 그런 다음 "./"를 추가하여 빈 문자열 대소 문자를 처리 readlink -f
하고 전체 경로로 변환하는 데 사용하십시오
.
git-root
이 기술을 적용하기 위해 PATH에서 쉘 스크립트로 명령을 작성할 수도 있습니다 .
cat > ~/bin/git-root << EOF
#!/bin/sh -e
cdup=$(git rev-parse --show-cdup)
exec readlink -f ./$cdup
EOF
chmod 755 ~/bin/git-root
(위의 내용은 터미널에 붙여 넣어 git-root를 생성하고 실행 비트를 설정할 수 있습니다. 실제 스크립트는 2, 3, 4 행에 있습니다.)
그런 다음 git root
현재 트리의 루트를 얻기 위해 실행할 수 있습니다 . 쉘 스크립트에서, "-e"를 사용하여 rev 구문 분석에 실패한 경우 쉘이 종료되도록하여 git 디렉토리에 있지 않은 경우 종료 상태 및 오류 메시지를 올바르게 얻을 수 있습니다.
"$(git rev-parse ...)"
같은 핵 대신 사용하십시오 ./$(git rev-parse ...)
.
다른 사람들이 지적했듯이 솔루션의 핵심은 사용하는 것 git rev-parse --show-cdup
입니다. 그러나 해결해야 할 몇 가지 중요한 경우가 있습니다.
cwd가 이미 작업 트리의 루트 인 경우 명령은 빈 문자열을 생성합니다.
실제로는 빈 줄을 생성하지만 명령 대체는 후행 줄 바꿈을 제거합니다. 최종 결과는 빈 문자열입니다.
대부분의 답변 ./
은 빈 출력이 "./"
공급되기 전에 출력이 앞에 오도록 제안 합니다 cd
.
GIT_WORK_TREE가 cwd의 상위가 아닌 위치로 설정되면 출력은 절대 경로 이름 일 수 있습니다.
./
이 상황에서는 앞에 붙는 것이 잘못되었습니다. a ./
가 절대 경로 앞에 추가되면 상대 경로가됩니다 (cwd가 시스템의 루트 디렉토리 인 경우 동일한 위치 만 참조 함).
출력에 공백이 포함될 수 있습니다.
이것은 실제로 두 번째 경우에만 적용되지만 쉬운 수정이 있습니다. 명령 대체 (및 이후의 값 사용) 주위에 큰 따옴표를 사용하십시오.
다른 답변에서 알 수 있듯이 우리는 할 수 cd "./$(git rev-parse --show-cdup)"
있지만 두 번째 엣지 케이스 (및 큰 따옴표를 제외하면 세 번째 엣지 케이스)에서 중단됩니다.
많은 쉘 cd ""
은 no-op로 취급 하므로 쉘에서 할 수 있습니다 cd "$(git rev-parse --show-cdup)"
(큰 따옴표는 빈 문자열을 첫 번째 가장자리의 경우 인수로 보호하고 세 번째 가장자리의 경우 공백을 유지합니다). POSIX에 따르면 결과 cd ""
가 불특정이므로이 가정을하지 않는 것이 가장 좋습니다.
위의 모든 경우에 작동하는 솔루션에는 일종의 테스트가 필요합니다. 명시 적으로 완료하면 다음과 같이 보일 수 있습니다.
cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"
cd
첫 번째 경우에는 수행 되지 않습니다 .
cd .
첫 번째 에지 케이스에 대해 실행하는 것이 허용 가능한 경우 매개 변수를 확장하여 조건부를 수행 할 수 있습니다.
cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
git root
위의 대답이 사용 하는 쉘 별명 gitroot = 'cd '를 사용하지 않습니까?
하위 모듈, 후크 및 .git
디렉토리 내부에서 작동하는 간단한 솔루션
가장 원하는 답은 다음과 같습니다.
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"
이것은 .git
디렉토리 내부를 포함하여 git working tree의 어느 곳에서나 작동 하지만 저장소 디렉토리가 호출된다고 가정합니다 ( .git
기본값). 하위 모듈을 사용하면 가장 바깥에있는 저장소의 루트로 이동합니다.
현재 서브 모듈의 루트로 가려면 다음을 사용하십시오.
echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))
하위 모듈 루트에서 명령을 쉽게 실행하려면 아래 [alias]
에서 다음 .gitconfig
을 추가하십시오.
sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"
이를 통해 다음과 같은 작업을 쉽게 수행 할 수 있습니다 git sh ag <string>
다른 이름 또는 외부 .git
또는 $GIT_DIR
디렉토리 를 지원하는 강력한 솔루션 .
주 $GIT_DIR
어딘가에 외부 지적 할 수있다 (그리고 호출 할 .git
추가 검사에 따라서 필요).
이것을 당신의 것으로 넣으십시오 .bashrc
:
# Print the name of the git working tree's root directory
function git_root() {
local root first_commit
# git displays its own error if not in a repository
root=$(git rev-parse --show-toplevel) || return
if [[ -n $root ]]; then
echo $root
return
elif [[ $(git rev-parse --is-inside-git-dir) = true ]]; then
# We're inside the .git directory
# Store the commit id of the first commit to compare later
# It's possible that $GIT_DIR points somewhere not inside the repo
first_commit=$(git rev-list --parents HEAD | tail -1) ||
echo "$0: Can't get initial commit" 2>&1 && false && return
root=$(git rev-parse --git-dir)/.. &&
# subshell so we don't change the user's working directory
( cd "$root" &&
if [[ $(git rev-list --parents HEAD | tail -1) = $first_commit ]]; then
pwd
else
echo "$FUNCNAME: git directory is not inside its repository" 2>&1
false
fi
)
else
echo "$FUNCNAME: Can't determine repository root" 2>&1
false
fi
}
# Change working directory to git repository root
function cd_git_root() {
local root
root=$(git_root) || return 1 # git_root will print any errors
cd "$root"
}
입력하여 실행 git_root
(쉘을 다시 시작한 후 : exec bash
)
(root=$(git rev-parse --git-dir)/ && cd ${root%%/.git/*} && git rev-parse && pwd)
그러나 이것 $GIT_DIR
이외의 다른 이름은 다루지 않습니다.git
git-extras
에 추가해 $ git root
볼 https://github.com/tj/git-extras/blob/master/Commands.md#git-root
$ pwd
.../very-deep-from-root-directory
$ cd `git root`
$ git add . && git commit
$ brew install git-extras
$ apt-get install git-extras
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'
다른 모든 것은 어느 시점에서 홈 디렉토리로 이동하거나 비참하게 실패합니다. 이것이 GIT_DIR로 돌아가는 가장 빠르고 짧은 방법입니다.
$GIT_DIR
-Files 및를 사용하여 작업 .git
트리 에서 분리 하면 실패합니다 gitdir: SOMEPATH
. 결과적으로 $GIT_DIR
포함 하는 하위 모듈에서도 실패합니다 .git/modules/SUBMODULEPATH
.
다음은 두 가지 경우를 모두 처리하는 스크립트입니다. 1) 작업 영역이있는 저장소, 2) 기본 저장소.
https://gist.github.com/jdsumsion/6282953
git-root
(경로의 실행 파일) :
#!/bin/bash
GIT_DIR=`git rev-parse --git-dir` &&
(
if [ `basename $GIT_DIR` = ".git" ]; then
# handle normal git repos (with a .git dir)
cd $GIT_DIR/..
else
# handle bare git repos (the repo IS a xxx.git dir)
cd $GIT_DIR
fi
pwd
)
희망적으로 이것은 도움이됩니다.
git exec
아이디어가 베어 리포지토리에 더 도움이 된다는 것을 깨달았 기 때문에 실제로 가장 많이 대답했습니다 . 그러나 내 대답에있는이 스크립트는 베어 대 비 베어 케이스를 올바르게 처리하여 누군가에게 유용 할 수 있으므로 여기 에이 답변을 남겨 두겠습니다.
git submodule
곳에서 실패합니다 . 또한 디렉토리가 맨손이 아닌 경우 작업 트리의 일부 라고 가정 합니다. $GIT_DIR
/.git/modules/SUBMODULE
.git
$ git config alias.root '!pwd'
# then you have:
$ git root
[alias] findroot = "!f () { [[ -d ".git" ]] && echo "Found git in [
pwd ]" && exit 0; cd .. && echo "IN
pwd" && f;}; f"
git config --global alias.root '!pwd'
작동합니다. 비전 역 변형과 다르게 작동하는 경우를 발견 할 수 없었습니다. BTW (유닉스, 1.7.10.4를 이눔) : 귀하는 findroot
필요 /.git
끝없는 재귀를 피하기 위해.
Git 2.13.0 부터는 루트 프로젝트의 경로를 표시하는 새로운 옵션을 지원하며 서브 모듈 내부에서 사용될 때도 작동합니다.
git rev-parse --show-superproject-working-tree
쉘 프레임 워크를 사용하는 경우 이미 사용 가능한 쉘 별명이있을 수 있습니다.
$ grt
에서 오 - 내 - zsh을 (68K) ( cd $(git rev-parse --show-toplevel || echo ".")
)$ git-root
에서 prezto (8.8k) (표시 작업 트리 루트의 경로)$ g..
zimfw (1k) (현재 디렉토리를 작업 트리의 최상위 레벨로 변경합니다.)나는 Daniel Brockman의 훌륭한 논평을 확장하고 싶었다.
정의 git config --global alias.exec '!exec '
하면 다음과 같은 git exec make
이유로 다음 과 같은 작업을 수행 할 수 있습니다 man git-config
.
별명 확장 앞에 느낌표가 있으면 쉘 명령으로 취급됩니다. [...] 쉘 명령은 저장소의 최상위 디렉토리에서 실행되며 반드시 현재 디렉토리 일 필요는 없습니다.
또한 $GIT_PREFIX
저장소의 최상위 디렉토리에 상대적인 현재 디렉토리의 경로가 될 것임을 알면 편리 합니다. 그러나이 사실을 아는 것은 전투의 절반에 불과합니다. 쉘 변수 확장은 사용하기가 다소 어렵습니다. 따라서 다음 bash -c
과 같이 사용하는 것이 좋습니다 .
git exec bash -c 'ls -l $GIT_PREFIX'
다른 명령은 다음과 같습니다.
git exec pwd
git exec make
git
실행 파일 이 없어도 POSIX 호환 방법이 필요한 사람은 다음과 같습니다.
#$1: Path to child directory
git_root_recurse_parent() {
# Check if cwd is a git root directory
if [ -d .git/objects -a -d .git/refs -a -f .git/HEAD ] ; then
pwd
return 0
fi
# Check if recursion should end (typically if cwd is /)
if [ "${1}" = "$(pwd)" ] ; then
return 1
fi
# Check parent directory in the same way
local cwd=$(pwd)
cd ..
git_root_recurse_parent "${cwd}"
}
git_root_recurse_parent
스크립트의 일부로 기능을 원하면 shebang을 제거하고 마지막 git_root_recurse_parent
행을 다음으로 바꾸십시오 .
git_root() {
(git_root_recurse_parent)
}
if
문장은 재귀에서 디렉토리를 변경했는지 여부를 확인해야했습니다. 그것이 같은 디렉토리에 남아 있다면, 그것은 당신이 어딘가에 붙어 있다고 가정하고 (예를 들어 /
브레이크 재귀). 버그가 수정되었으며 이제 예상대로 작동합니다. 지적 해 주셔서 감사합니다.
오늘이 문제를 직접 해결해야했습니다. 프로그램에 필요할 때 C #으로 해결했지만 재 작성 할 수 있다고 생각합니다. 이 공개 도메인을 고려하십시오.
public static string GetGitRoot (string file_path) {
file_path = System.IO.Path.GetDirectoryName (file_path);
while (file_path != null) {
if (Directory.Exists (System.IO.Path.Combine (file_path, ".git")))
return file_path;
file_path = Directory.GetParent (file_path).FullName;
}
return null;
}