Existe uma maneira de obter o diretório raiz do git em um comando?

a Mercurial tem uma forma de imprimir o directório raiz (que contém .HG) via

hg root

Existe algo equivalente no git para obter o diretório que contém o .directório git?

Author: Rob Kennedy, 2009-06-06

21 answers

Sim:

git rev-parse --show-toplevel
 830
Author: baudtack, 2015-07-03 10:29:44

A página man Para git-config (Sob Também conhecido por ) diz:

Se a expansão da alcunha for precedida de um ponto de exclamação, será tratada como uma concha comando. Por exemplo, definir "alias".new = !gitk -- all -- not ORIG_HEAD", a invocação "git new "é equivalente a executar o comando shell "gitk -- all --not ORIG_HEAD". Note que a consola os comandos serão executados a partir do directório de topo de um repositório, o qual poderá não ser necessariamente a corrente Directorio.

Então, no UNIX você pode fazer:

git config --global --add alias.root '!pwd'
 88
Author: Scott Lindsay, 2013-05-17 13:11:34

Só recentemente foi adicionado a git rev-parse ou porque é que ninguém o menciona?

Da página do homem:

   --show-toplevel
       Show the absolute path of the top-level directory.
 84
Author: marc.guenther, 2010-09-10 18:14:49
Que tal ... "git rev-parse --git-dir" ?
F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git

A opção --git-dir parece funcionar.

From git rev-parse manual page:

--git-dir

    Show $GIT_DIR if defined else show the path to the .git directory.

Você pode vê-lo em ação neste git setup-sh script .

 37
Author: VonC, 2009-06-05 21:01:05

Se já estiver no nível superior ou não num repositório git {[[0]} irá levá-lo para casa (apenas cd). cd ./$(git rev-parse --show-cdup) é uma maneira de resolver isso.

 26
Author: Karl, 2009-06-15 07:07:43

Para escrever uma resposta simples aqui, para que possamos usar

git root

Para fazer o trabalho, basta configurar o seu git usando

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

E então você pode querer adicionar o seguinte ao seu ~/.bashrc:

alias cdroot='cd $(git root)'

De modo que você pode apenas usar cdroot para ir para o topo do seu repo.

 24
Author: 太極者無極而生, 2017-09-30 07:43:47

Para calcular a localização absoluta da pasta de raiz do git actual, por exemplo, para usar num programa de consola, use esta combinação de readlink e git rev-parse:

gitroot=$(readlink -f ./$(git rev-parse --show-cdup))

git-rev-parse --show-cdup dá-lhe o número certo de".."s para obter para a raiz de seu cwd, ou a cadeia vazia se você estiver na raiz. Então prepara "./ "para lidar com a caixa de texto vazia e usar readlink -f traduzir para um caminho completo.

Você também pode criar um comando git-root no seu caminho como um script de shell para aplicar isto técnica:

cat > ~/bin/git-root << EOF
#!/bin/sh -e
cdup=$(git rev-parse --show-cdup)
exec readlink -f ./$cdup
EOF
chmod 755 ~/bin/git-root

(o texto acima pode ser colado num terminal para criar git-root e definir bits de execução; o programa actual está nas linhas 2, 3 e 4.)

E depois serias capaz de correr para obter a raiz da tua árvore actual. Note que no script shell, use "-e" para fazer com que a shell saia se o rev-parse falhar de modo que você possa obter corretamente o estado de saída e mensagem de erro se você não estiver em um diretório git.
 16
Author: Emil Sit, 2010-06-09 19:48:55

Como outros observaram, o núcleo da solução é usar git rev-parse --show-cdup. No entanto, existem alguns casos extremos para resolver:

  1. Quando o cwd já é a raiz da árvore de trabalho, o comando produz uma cadeia vazia.
    na verdade, produz uma linha vazia, mas a substituição de comandos sai da quebra da linha de fuga. O resultado final é um texto vazio.

    A maioria das respostas sugere que se prepare o resultado com ./ para que um resultado vazio se torne "./" antes de ser alimentado a cd.

  2. Quando o GIT_WORK_TREE está definido para um local que não é o pai da cwd, o resultado pode ser um nome de caminho absoluto.

    A pré-venda ./ está errada nesta situação. Se um ./ é pré-adicionado a um caminho absoluto, ele se torna um caminho relativo (e eles só se referem ao mesmo local se o cwd é o diretório raiz do sistema).

  3. A saída pode conter espaços em branco.

    Isto só se aplica em o segundo caso, mas tem uma correção fácil: use aspas duplas em torno da substituição de comandos (e quaisquer usos subsequentes do valor).

Como outras respostas observaram, podemos fazer {[[8]}, mas isto quebra no segundo caso edge (e o terceiro caso edge se deixarmos as aspas duplas).

Muitas conchas tratam cd "" como um no-op, de modo que para essas conchas nós poderíamos fazer cd "$(git rev-parse --show-cdup)" (as aspas duplas protegem o texto vazio como um argumento no primeiro caso edge, e preservam espaços em branco in the third edge case). POSIX diz que o resultado de cd "" é indeterminado, então pode ser melhor evitar fazer esta suposição.

Uma solução que funcione em todos os casos acima requer um teste de algum tipo. Feito explicitamente, pode parecer assim:

cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"

Não cd está pronto para a primeira caixa.

Se for aceitável executar cd . para o primeiro caso de aresta, então o condicional pode ser feito na expansão do parâmetro:

cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
 15
Author: Chris Johnsen, 2010-07-05 05:14:46

Soluções curtas que funcionam com submódulos, ganchos e dentro da pasta .git

Aqui está a resposta curta que a maioria vai querer:
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"

Isto irá funcionar em qualquer parte de uma árvore de trabalho git( incluindo dentro do directório .git), mas assume que o(s) directório (s) do repositório (s) são chamados .git (que é o padrão). Com submódulos, isso vai para a raiz do repositório externo contendo.

Se queres chegar à raiz da corrente utilização do submódulo:

echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))

Para executar facilmente um comando na sua raiz submódula, em [alias] no seu .gitconfig, adicionar:

sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"
Isto permite-lhe fazer coisas como:git sh ag <string>

Solução robusta que suporta pastas com nomes diferentes ou externas .git ou $GIT_DIR.

Note que $GIT_DIR pode apontar para algum lugar externo( e não ser chamado .git), daí a necessidade de mais verificações.

Põe isto no teu ... .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 # git_root will print any errors
  cd "$root"
}
Execute-o por dactilografia git_root (após reiniciar a sua casca: exec bash)
 10
Author: Tom Hale, 2016-08-10 06:43:33

Só para o caso de estares a dar este caminho ao próprio Git, usa :/

# 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)
 9
Author: Nick Volynkin, 2017-08-14 13:37:07

Para alterar a resposta" git config " apenas um pouco:

git config --global --add alias.root '!pwd -P'
E limpa o caminho. Bom.
 8
Author: Bruce K, 2012-07-25 14:12:58

Se está à procura de um bom pseudónimo para fazer isto e não explodir cd Se não está num git dir:

alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'
 7
Author: Dan Heberden, 2012-07-30 20:49:55

Esta alcunha da shell funciona quer esteja numa sub-pasta git, quer no nível superior:

alias gr='[ ! -z `git rev-parse --show-toplevel` ] && cd `git rev-parse --show-toplevel || pwd`'

Actualizado para usar a sintaxe moderna em vez de retoques:

alias gr='[ ! -z $(git rev-parse --show-toplevel) ] && cd $(git rev-parse --show-toplevel || pwd)'
 6
Author: MERM, 2016-01-19 03:43:47
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'
{[[2]} tudo o resto falha em algum momento, seja indo para o diretório home ou simplesmente falhando miseravelmente. Este é o caminho mais rápido e mais curto para voltar ao GIT_DIR.
 5
Author: tocororo, 2012-07-25 14:12:33

Aqui está um script que eu escrevi que lida com ambos os casos: 1) repositório com um espaço de trabalho, 2) repositório bare.

Https://gist.github.com/jdsumsion/6282953

git-root (ficheiro executável na sua localização):

#!/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
)
Espero que isto seja útil.
 5
Author: jdsumsion, 2013-08-20 17:08:11

git-extras

Adiciona $ git root
ver 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

Disponibilidade de git-extras

 5
Author: Hotschke, 2018-02-24 03:11:20
$ git config alias.root '!pwd'
# then you have:
$ git root
 4
Author: FractalSpace, 2013-01-12 17:53:55

Desde O Git 2. 13. 0 , suporta uma nova opção para mostrar a localização do projecto root, que funciona mesmo quando é usado dentro de um submódulo:

git rev-parse --show-superproject-working-tree
 3
Author: Jordi Vilalta Prat, 2018-05-16 09:25:33
Tive de resolver isto hoje. Resolvi-o em C# como precisava para um programa, mas acho que pode ser reescrito. Considere este domínio público.
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;

}
 1
Author: Hylke Bons, 2010-07-04 22:49:13

Alcunhas de consola pré-configuradas em Frameworks

Se utilizar um shell framework, poderá já existir um shell alias disponível:

  • $ grt in oh-my-zsh (68k) (cd $(git rev-parse --show-toplevel || echo "."))
  • $ git-root in prezto (8, 8 k) (mostra o caminho para a raiz da árvore de trabalho)
  • $ g.. zimfw (1k) (muda a pasta actual para o nível superior da árvore de trabalho.)
 1
Author: Hotschke, 2018-04-11 06:03:30

No caso de alguém precisar de uma forma compatível com POSIX de fazer isto, sem precisar de git executável:

git-root:

#!/bin/sh

#$1: Path to child directory
recurse_parent() {

    if is_cwd_git_root ; then
        pwd
        return 0
    fi

    if [ "${1}" = "$(pwd)" ] ; then
        return 1
    fi

    cd ..
    recurse_parent "${CWD}"


}

is_cwd_git_root() {
    [ -d .git/branches -a -d .git/objects -a -d .git/refs -a -f .git/HEAD ]
}

recurse_parent
 0
Author: swalog, 2018-09-09 03:42:10