Mercurial有一种打印根目录(包含.hg)的方法
hg root
git中是否有等价的东西来获取包含.git目录的目录?
Mercurial有一种打印根目录(包含.hg)的方法
hg root
git中是否有等价的东西来获取包含.git目录的目录?
当前回答
在钩子和.git目录中使用子模块的简短解决方案
这是大多数人想要的简短答案:
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"
这将在git工作树中的任何地方工作(包括在.git目录中),但假设存储库目录被称为.git(这是默认的)。对于子模块,这将转到包含最外层存储库的根。
如果你想获得当前子模块的根,使用:
echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))
为了在你的根模块中轻松地执行一个命令,在你的.gitconfig中的[alias]下,添加:
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来执行它(在重新启动shell后:exec bash)
其他回答
Yes:
git rev-parse --show-toplevel
如果你想更直接地复制Mercurial命令,你可以创建一个别名:
git config --global alias.root 'rev-parse --show-toplevel'
现在git根和hg根一样。
注意:在子模块中,这将显示子模块的根目录,而不是父存储库。如果您使用的是Git >=2.13或更高版本,有一种方法可以让子模块显示超级项目的根目录。如果你的git比这更老,请参阅另一个答案。
今天必须自己解决这个问题。在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;
}
如果你正在寻找一个好的别名来执行此操作,如果你不在git目录下,则不要放大cd:
alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'
——show- topllevel是最近才添加到git rev-parse的吗?为什么没有人提到它?
从git rev-parse手册页:
--show-toplevel
Show the absolute path of the top-level directory.
正如其他人所注意到的,解决方案的核心是使用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 to cd. 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).
正如其他答案所指出的,我们可以做cd”。/$(git rev-parse——show-cdup))”,但这会在第二个边缘大小写中中断(如果去掉双引号,则会在第三个边缘大小写中中断)。
许多shell将cd ""视为无操作,因此对于这些shell,我们可以执行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:-.}"