当前位置:  开发笔记 > 编程语言 > 正文

有没有办法在一个命令中获取git根目录?

如何解决《有没有办法在一个命令中获取git根目录?》经验,为你挑选了16个好方法。

Mercurial有一种打印根目录(包含.hg)的方法

hg root

在git中是否有类似的东西来获取包含.git目录的目录?



1> baudtack..:

是:

git rev-parse --show-toplevel

注意:在子模块中,这将显示子模块的根目录,而不是父存储库.


我总是定义`git config --global alias.exec'!exec'`所以我可以做`git exec make`之类的事情.这是有效的,因为shell别名总是在顶级目录中执行.
**注意**这不适用于子模块中.
对此解决方案的警告 - 它将跟进任何符号链接.所以,如果你在`〜/ my.proj/foo/bar`中,并且`〜/ my.proj`被符号链接到`〜/ src/my.proj`,上面的命令会把你带到`〜/ src/my.proj`.可能是一个问题,如果你想做什么之后不是树不可知的.
这个解决方案(以及我尝试过的这个页面上的许多其他解决方案)在git hook中不起作用.更确切地说,当你进入项目的`.git`目录时,它不起作用.
这就是`hg root`的作用.它打印出已签出存储库的顶级目录.它不会切换到它(实际上它不能这样做,因为当前目录和shell的整个概念如何交互).
我如何在git钩子中使用它?具体来说,我正在做一个合并后的钩子,我需要得到本地git repo的实际根目录.
这个`git rev-parse && cd"$(git rev-parse --show-cdup)`在一般情况下不起作用,因为`git rev-parse --show-cdup`返回空字符串,以防你是已经在git root dir.概念是你去你家.
正如@Dennis指出的那样,如果在`.git`目录(或者存储库的外部`$ GIT_DIR`)内部,这不起作用.请参阅我的答案,该答案适用于存储库中的任何位置,并且在外部`$优雅地失败GIT_DIR`

2> 小智..:

(Alias下)的man页面说:git-config

如果别名扩展以感叹号为前缀,则将其视为shell命令.[...]请注意,shell命令将从存储库的顶级目录执行,该目录可能不一定是当前目录.

所以,在UNIX上你可以这样做:

git config --global --add alias.root '!pwd'


在Windows系统上不起作用.另一个.
@Mechanicalsnail真的吗?那么你期望在外面回购什么呢?
@cormacrelf你不要把它放在shell别名中.您可以将它放在shell函数或脚本中.
@cormacrelf将它放在单引号而不是双引号中,然后它不会在定义时扩展,而是在运行时扩展.

3> marc.guenthe..:

--show-toplevel最近才加入git rev-parse或为什么没人提呢?

git rev-parse手册页:

   --show-toplevel
       Show the absolute path of the top-level directory.


特别是,您可以在gitconfig中使用别名`root = rev-parse --show-toplevel`.
换句话说,你可以做`git config --global alias.root"rev-parse --show-toplevel"`然后`git root`就能完成这项工作

4> VonC..:

" 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目录,而不是git repo的基础.此外,.git目录可能在其他地方,所以这不是我正在寻找的.
是的,我现在看到你真正想要的东西.--show-cdup比较合适.我留下我的答案来说明两个选项之间的区别.
如果你已经在根目录中,那么看起来这个命令给出了`.git`的相对路径.(至少,它在msysgit上.)
+1,这是回答原始问题"获取包含.git目录的目录?"的唯一答案,有趣的是看到OP本身提到".git目录可能在其他地方".

5> nopole..:

在这里写一个简单的答案,以便我们可以使用

git root

要完成这项工作,只需使用配置您的git即可

git config --global alias.root "rev-parse --show-toplevel"

然后你可能想要将以下内容添加到你的~/.bashrc:

alias cdroot='cd $(git root)'

这样你就可以用到cdroot你的回购顶部了.



6> Karl..:

如果您已经在顶级或不在git存储库中,cd $(git rev-parse --show-cdup)则会将您带回家(只需cd). cd ./$(git rev-parse --show-cdup)是解决这个问题的一种方法.


另一种选择是引用它:`cd"$(git rev-parse --show-cdup)"`.这是有效的,因为`cd""`带你无处可去,而不是回到'$ HOME`.最好引用$()调用,以防它们输出带空格的东西(不过在这种情况下不会使用此命令).

7> Chris Johnse..:

正如其他人所说,解决方案的核心是使用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:-.}"


+1列出角落案例!

8> Emil Sit..:

要计算当前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"root"目录路径包含空格,那么您的示例将会中断.总是使用`"$(git rev-parse ...)"`而不是像`./ $(git rev-parse ...)`这样的黑客.

9> Nick Volynki..:

如果您正在将此路径提供给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)



10> Tom Hale..:

使用子模块,挂钩和.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)执行它:



11> Bruce K..:

要修改"git config"答案:

git config --global --add alias.root '!pwd -P'

并清理道路.非常好.



12> Dan Heberden..:

如果你正在寻找一个好的别名来做这个加上cd如果你不是一个git目录就不要爆炸:

alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'



13> Hotschke..:

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

git-extras的可用性

自制(OSX)/ linuxbrew(Linux)的 $ brew install git-extras

debian/ubuntu repos(https://packages.debian.org/sid/git-extras)$ apt-get install git-extras



14> MERM..:

无论您是在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)'



15> tocororo..:
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'

其他一切都失败了,无论是去主页目录还是惨不忍睹.这是回到GIT_DIR的最快捷,最短的方式.


当使用`.git`-Files和`gitdir:SOMEPATH`将`$ GIT_DIR`与workingtree分离时,这会失败.因此,子模块也失败了,其中`$ GIT_DIR`包含`.git/modules/SUBMODULEPATH`.

16> jdsumsion..:

这是我编写的一个脚本,它处理两种情况: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
)

希望这很有帮助.

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有