有没有办法在一个命令中获取 git 根目录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/957928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to get the git root directory in one command?
提问by wojo
Mercurial has a way of printing the root directory (that contains .hg) via
Mercurial 有一种通过以下方式打印根目录(包含 .hg)的方法
hg root
Is there something equivalent in git to get the directory that contains the .git directory?
在 git 中是否有等效的东西来获取包含 .git 目录的目录?
回答by baudtack
Yes:
是的:
git rev-parse --show-toplevel
If you want to replicate the Git command more directly, you can create an alias:
如果你想更直接地复制 Git 命令,你可以创建一个别名:
git config --global alias.root 'rev-parse --show-toplevel'
and now git root
will function just as hg root
.
现在git root
就像hg root
.
Note: In a submodule this will display the root directory of the submoduleand notthe parent repository. If you are using Git >=2.13 or above, there is a way that submodules can show the superproject's root directory.If your git is older than that, see this other answer.
注:在一个子模块,这将显示的根目录下的子模块,并没有父库。如果你使用 Git >=2.13 或更高版本,子模块可以通过一种方式显示超级项目的根目录。如果您的 git 比这更旧,请参阅其他答案。
回答by Scott Lindsay
The man
page for git-config
(under Alias) says:
(在Alias下)的man
页面说:git-config
If the alias expansion is prefixed with an exclamation point, it will be treated as a shell command. [...] Note that shell commands will be executed from the top-level directory of a repository, which may not necessarily be the current directory.
如果别名扩展以感叹号为前缀,它将被视为一个 shell 命令。[...] 请注意,shell 命令将从存储库的顶级目录执行,该目录可能不一定是当前目录。
So, on UNIX you can do:
因此,在 UNIX 上,您可以执行以下操作:
git config --global --add alias.root '!pwd'
回答by marc.guenther
Has --show-toplevel
only recently been added to git rev-parse
or why is nobody mentioning it?
有--show-toplevel
最近才加入git rev-parse
或为什么没人提呢?
From the git rev-parse
man page:
从git rev-parse
手册页:
--show-toplevel
Show the absolute path of the top-level directory.
回答by VonC
How about "git rev-parse --git-dir
" ?
“ git rev-parse --git-dir
”怎么样?
F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git
The --git-dir
option seems to work.
该--git-dir
选项似乎有效。
From git rev-parse manual page:
--git-dir
Show $GIT_DIR if defined else show the path to the .git directory.
You can see it in action in this git setup-sh
script.
您可以在此git setup-sh
脚本中看到它的运行情况。
If you are in a submodule folder, with Git >=2.13, use:
如果您在子模块文件夹中,并且 Git >=2.13,请使用:
git rev-parse --show-superproject-working-tree
If you are using git rev-parse --show-toplevel
, make sure it is with Git 2.25+ (Q1 2020).
如果您使用的是git rev-parse --show-toplevel
,请确保它与 Git 2.25+ (Q1 2020) 一起使用。
回答by nonopolarity
To write a simple answer here, so that we can use
在这里写一个简单的答案,以便我们可以使用
git root
to do the job, simply configure your git by using
要完成这项工作,只需使用
git config --global alias.root "rev-parse --show-toplevel"
and then you might want to add the following to your ~/.bashrc
:
然后您可能希望将以下内容添加到您的~/.bashrc
:
alias cdroot='cd $(git root)'
so that you can just use cdroot
to go to the top of your repo.
这样您就可以使用cdroot
转到您的回购的顶部。
回答by Karl
If you're already in the top-level or not in a git repository cd $(git rev-parse --show-cdup)
will take you home (just cd). cd ./$(git rev-parse --show-cdup)
is one way of fixing that.
如果您已经在顶级或不在 git 存储库中,cd $(git rev-parse --show-cdup)
将带您回家(只需 cd)。 cd ./$(git rev-parse --show-cdup)
是解决这个问题的一种方法。
回答by Emil Sit
To calculate the absolute path of the current git root directory, say for use in a shell script, use this combination of readlink and git rev-parse:
要计算当前 git 根目录的绝对路径,比如在 shell 脚本中使用,请使用 readlink 和 git rev-parse 的组合:
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdup
gives you the right number of ".."s to get
to the root from your cwd, or the empty string if you are at the root.
Then prepend "./" to deal with the empty string case and use
readlink -f
to translate to a full path.
git-rev-parse --show-cdup
为您提供正确数量的“..”以从您的 cwd 到达根目录,或者如果您位于根目录,则为空字符串。然后在前面加上“./”来处理空字符串情况并用于
readlink -f
转换为完整路径。
You could also create a git-root
command in your PATH as a shell script to apply this technique:
您还可以git-root
在 PATH 中创建一个命令作为 shell 脚本来应用此技术:
cat > ~/bin/git-root << EOF
#!/bin/sh -e
cdup=$(git rev-parse --show-cdup)
exec readlink -f ./$cdup
EOF
chmod 755 ~/bin/git-root
(The above can be pasted into a terminal to create git-root and set execute bits; the actual script is in lines 2, 3 and 4.)
(以上内容可以粘贴到终端中以创建 git-root 并设置执行位;实际脚本在第 2、3 和 4 行。)
And then you'd be able to run git root
to get the root of your current tree.
Note that in the shell script, use "-e" to cause the shell to exit if the rev-parse fails so that you can properly get the exit status and error message if you are not in a git directory.
然后您就可以运行git root
以获取当前树的根。请注意,在 shell 脚本中,如果 rev-parse 失败,请使用“-e”使 shell 退出,以便在您不在 git 目录中时可以正确获取退出状态和错误消息。
回答by Chris Johnsen
As others have noted, the core of the solution is to use git rev-parse --show-cdup
. However, there are a few of edge cases to address:
正如其他人所指出的,解决方案的核心是使用git rev-parse --show-cdup
. 但是,有一些边缘情况需要解决:
When the cwd already is the root of the working tree, the command yields an empty string.
Actually it produces an empty line, but command substitution strip off the trailing line break. The final result is an empty string.Most answers suggest prepending the output with
./
so that an empty output becomes"./"
before it is fed tocd
.When GIT_WORK_TREE is set to a location that is not the parent of the cwd, the output may be an absolute pathname.
Prepending
./
is wrong in this situation. If a./
is prepended to an absolute path, it becomes a relative path (and they only refer to the same location if the cwd is the root directory of the system).The output may contain whitespace.
This really only applies in the second case, but it has an easy fix: use double quotes around the command substitution (and any subsequent uses of the value).
当 cwd 已经是工作树的根时,该命令会产生一个空字符串。
实际上它会产生一个空行,但是命令替换会去掉尾随的换行符。最终结果是一个空字符串。大多数答案建议在输出前加上 ,
./
以便"./"
在将其馈送到cd
.当 GIT_WORK_TREE 设置为不是 cwd 父级的位置时,输出可能是绝对路径名。
./
在这种情况下,前置是错误的。如果在./
绝对路径前面加上a ,它就变成了相对路径(如果 cwd 是系统的根目录,它们只引用相同的位置)。输出可能包含空格。
这实际上仅适用于第二种情况,但它有一个简单的解决方法:在命令替换(以及该值的任何后续使用)周围使用双引号。
As other answers have noted, we can do cd "./$(git rev-parse --show-cdup)"
, but this breaks in the second edge case (and the third edge case if we leave off the double quotes).
正如其他答案所指出的那样,我们可以这样做cd "./$(git rev-parse --show-cdup)"
,但这会在第二个边缘情况下(如果我们不使用双引号,则在第三个边缘情况下会中断)。
Many shells treat cd ""
as a no-op, so for those shells we could do cd "$(git rev-parse --show-cdup)"
(the double quotes protect the empty string as an argument in the first edge case, and preserve whitespace in the third edge case). POSIX says the result of cd ""
is unspecified, so it may be best to avoid making this assumption.
许多 shell 将其cd ""
视为无操作,因此对于我们可以做的那些 shell cd "$(git rev-parse --show-cdup)"
(双引号在第一个边缘情况下保护空字符串作为参数,并在第三个边缘情况下保留空格)。POSIX 说 的结果cd ""
未指定,因此最好避免做出这种假设。
A solution that works in all of the above cases requires a test of some sort. Done explicitly, it might look like this:
适用于上述所有情况的解决方案需要进行某种测试。明确完成后,它可能如下所示:
cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"
No cd
is done for the first edge case.
cd
对于第一个边缘情况没有完成。
If it is acceptable to run cd .
for the first edge case, then the conditional can be done in the expansion of the parameter:
如果cd .
对于第一个边缘情况运行是可以接受的,那么可以在参数的扩展中完成条件:
cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
回答by Nick Volynkin
Just in case if you're feeding this path to the Git itself, use :/
以防万一,如果您将此路径提供给 Git 本身,请使用 :/
# this adds the whole working tree from any directory in the repo
git add :/
# and is equal to
git add $(git rev-parse --show-toplevel)
回答by Tom Hale
Short solutions that work with submodules, in hooks, and inside the .git
directory
适用于子模块、钩子和.git
目录内部的简短解决方案
Here's the short answer that most will want:
这是大多数人想要的简短答案:
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"
This will work anywhere in a git working tree (including inside the .git
directory), but assumes that repository directory(s) are called .git
(which is the default). With submodules, this will go to the root of the outermost containing repository.
这将适用于 git 工作树中的任何位置(包括.git
目录内部),但假设调用了存储库目录.git
(这是默认值)。对于子模块,这将转到最外层包含存储库的根目录。
If you want to get to the root of the current submodule use:
如果要访问当前子模块的根目录,请使用:
echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))
To easily execute a command in your submodule root, under [alias]
in your .gitconfig
, add:
要在您的子模块根目录中轻松执行命令,请[alias]
在您的下.gitconfig
添加:
sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"
This allows you to easily do things like git sh ag <string>
这使您可以轻松地执行以下操作 git sh ag <string>
Robust solution that supports differently named or external .git
or $GIT_DIR
directories.
支持不同命名或外部.git
或$GIT_DIR
目录的强大解决方案。
Note that $GIT_DIR
may point somewhere external (and not be called .git
), hence the need for further checking.
请注意,$GIT_DIR
可能指向外部某个地方(而不是被调用.git
),因此需要进一步检查。
Put this in your .bashrc
:
把它放在你的.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 "##代码##: 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"
}
Execute it by typing git_root
(after restarting your shell: exec bash
)
通过键入执行它git_root
(重新启动后壳:exec bash
)