Mercurial有一种打印根目录(包含.hg)的方法
hg root
在git中是否有类似的东西来获取包含.git目录的目录?
是:
git rev-parse --show-toplevel
注意:在子模块中,这将显示子模块的根目录,而不是父存储库.
(Alias下)的man
页面说:git-config
如果别名扩展以感叹号为前缀,则将其视为shell命令.[...]请注意,shell命令将从存储库的顶级目录执行,该目录可能不一定是当前目录.
所以,在UNIX上你可以这样做:
git config --global --add alias.root '!pwd'
有--show-toplevel
最近才加入git rev-parse
或为什么没人提呢?
从git rev-parse
手册页:
--show-toplevel Show the absolute path of the top-level directory.
" 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 rev-parse手册页:
--git-dir Show $GIT_DIR if defined else show the path to the .git directory.
您可以在此git setup-sh
脚本中看到它的运行情况.
如果您在子模块文件夹中,使用Git 2.20,请使用:
git rev-parse --show-superproject-working-tree
在这里写一个简单的答案,以便我们可以使用
git root
要完成这项工作,只需使用配置您的git即可
git config --global alias.root "rev-parse --show-toplevel"
然后你可能想要将以下内容添加到你的~/.bashrc
:
alias cdroot='cd $(git root)'
这样你就可以用到cdroot
你的回购顶部了.
如果您已经在顶级或不在git存储库中,cd $(git rev-parse --show-cdup)
则会将您带回家(只需cd). cd ./$(git rev-parse --show-cdup)
是解决这个问题的一种方法.
正如其他人所说,解决方案的核心是使用git rev-parse --show-cdup
.但是,有一些边缘情况需要解决:
当cwd已经是工作树的根时,该命令产生一个空字符串.
实际上它产生一个空行,但命令替换剥离了尾随行.最终结果是一个空字符串.
大多数答案都建议在输出前加上./
一个空输出,"./"
然后输出cd
.
当GIT_WORK_TREE设置为不是cwd的父级的位置时,输出可以是绝对路径名.
./
在这种情况下,前置是错误的.如果a前./
置于绝对路径,则它将成为相对路径(如果cwd是系统的根目录,则它们仅指向相同的位置).
输出可能包含空格.
这实际上仅适用于第二种情况,但它有一个简单的解决方法:在命令替换(以及值的任何后续使用)周围使用双引号.
正如其他答案所指出的那样,我们可以这样做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:-.}"
要计算当前git根目录的绝对路径,比如在shell脚本中使用,请使用readlink和git rev-parse的这种组合:
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdup
从你的cwd中获取正确数量的".."以获取根目录,如果你位于根目录,则输入空字符串.然后在前面加上"./"来处理空字符串case并用于
readlink -f
转换为完整路径.
您还可以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
(以上内容可以粘贴到终端创建git-root并设置执行位;实际脚本位于第2,3和4行.)
然后你就可以运行git root
以获取当前树的根目录.请注意,在shell脚本中,如果rev-parse失败,请使用"-e"使shell退出,以便在不在git目录中时可以正确获取退出状态和错误消息.
如果您正在将此路径提供给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)
使用子模块,挂钩和.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) ))
要轻松执行子模块根目录中的命令,请[alias]
在您的下面.gitconfig
添加:
sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"
这可以让你轻松做到这样的事情 git sh ag
支持不同名称或外部.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
)执行它:
要修改"git config"答案:
git config --global --add alias.root '!pwd -P'
并清理道路.非常好.
如果你正在寻找一个好的别名来做这个加上cd
如果你不是一个git目录就不要爆炸:
alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'
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
自制(OSX)/ linuxbrew(Linux)的 $ brew install git-extras
debian/ubuntu repos(https://packages.debian.org/sid/git-extras)$ apt-get install git-extras
无论您是在git子目录中还是在顶层,这个shell别名都有效:
alias gr='[ ! -z `git rev-parse --show-toplevel` ] && cd `git rev-parse --show-toplevel || pwd`'
更新为使用现代语法而不是反引号:
alias gr='[ ! -z $(git rev-parse --show-toplevel) ] && cd $(git rev-parse --show-toplevel || pwd)'
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'
其他一切都失败了,无论是去主页目录还是惨不忍睹.这是回到GIT_DIR的最快捷,最短的方式.
这是我编写的一个脚本,它处理两种情况: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 )
希望这很有帮助.