example - git pull origin master
¿Hay una manera de obtener el directorio raíz git en un comando? (21)
Mercurial tiene una forma de imprimir el directorio raíz (que contiene .hg) a través de
hg root
¿Hay algo equivalente en git para obtener el directorio que contiene el directorio .git?
Alias de Shell preconfigurados en marcos de shell
Si usa un marco de shell, es posible que ya haya un alias de shell disponible:
-
$ grt
en oh-my-zsh (68k) (cd $(git rev-parse --show-toplevel || echo ".")
) -
$ git-root
en prezto (8.8k) (muestra la ruta a la raíz del árbol de trabajo) -
$ g..
zimfw (1k) (cambia el directorio actual al nivel superior del árbol de trabajo).
git-extras
agrega $ git root
vea 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
Disponibilidad de git-extras.
- homebrew (osx) / linuxbrew (linux)
$ brew install git-extras
- debian / ubuntu repos ( https://packages.debian.org/sid/git-extras )
$ apt-get install git-extras
¿Qué tal " git rev-parse --git-dir
"?
F:/prog/git/test/copyMerge/dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git
La opción --git-dir
parece funcionar.
Desde la página de manual de git rev-parse :
--git-dir
Show $GIT_DIR if defined else show the path to the .git directory.
Puedes verlo en acción en este script git setup-sh
.
Si está en una carpeta de submódulos, con Git 2.20 , use :
git rev-parse --show-superproject-working-tree
¿Se ha agregado recientemente --show-toplevel
a git rev-parse
o por qué nadie lo menciona?
Desde la página del manual de git rev-parse
:
--show-toplevel
Show the absolute path of the top-level directory.
Aquí hay un script que he escrito que maneja ambos casos: 1) repositorio con un espacio de trabajo, 2) repositorio simple.
https://gist.github.com/jdsumsion/6282953
git-root
(archivo ejecutable en su ruta):
#!/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
)
Esperemos que esto sea útil.
Como han señalado otros, el núcleo de la solución es usar git rev-parse --show-cdup
. Sin embargo, hay algunos de los casos de borde para abordar:
Cuando el cwd ya es la raíz del árbol de trabajo, el comando produce una cadena vacía.
En realidad, produce una línea vacía, pero la sustitución de comandos elimina el salto de línea posterior. El resultado final es una cadena vacía.La mayoría de las respuestas sugieren anteponer la salida con
./
para que una salida vacía se convierta en"./"
antes de que se alimente acd
.Cuando GIT_WORK_TREE se establece en una ubicación que no es la principal de cwd, la salida puede ser una ruta de acceso absoluta.
Anteponer
./
está mal en esta situación. Si un./
se añade a una ruta absoluta, se convierte en una ruta relativa (y solo se refieren a la misma ubicación si el cwd es el directorio raíz del sistema).La salida puede contener espacios en blanco.
Esto realmente solo se aplica en el segundo caso, pero tiene una solución fácil: use comillas dobles alrededor de la sustitución del comando (y cualquier uso posterior del valor).
Como han señalado otras respuestas, podemos hacer cd "./$(git rev-parse --show-cdup)"
, pero esto se rompe en el segundo caso de borde (y en el tercer caso de borde si dejamos las comillas dobles).
Muchos shells tratan el cd ""
como un no-op, así que para esos shells podríamos hacer el cd "$(git rev-parse --show-cdup)"
(las comillas dobles protegen la cadena vacía como un argumento en el primer caso de borde , y preservar los espacios en blanco en el caso del tercer borde). POSIX dice que el resultado de cd ""
no está especificado, por lo que puede ser mejor evitar este supuesto.
Una solución que funciona en todos los casos anteriores requiere una prueba de algún tipo. Hecho explícitamente, podría verse así:
cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"
No se hace cd
para el primer caso de borde.
Si es aceptable ejecutar cd .
para el primer caso de borde, entonces el condicional se puede hacer en la expansión del parámetro:
cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
Desde Git 2.13.0 , admite una nueva opción para mostrar la ruta del proyecto raíz, que funciona incluso cuando se usa desde un submódulo:
git rev-parse --show-superproject-working-tree
En caso de que alguien necesite una forma compatible con POSIX de hacer esto, sin necesidad de ejecutar git
:
#!/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
En caso de que esté alimentando este camino al Git en sí, use :/
# 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)
Este alias de shell funciona si estás en un subdirectorio git, o en el nivel superior:
alias gr=''[ ! -z `git rev-parse --show-toplevel` ] && cd `git rev-parse --show-toplevel || pwd`''
actualizado para usar la sintaxis moderna en lugar de backticks:
alias gr=''[ ! -z $(git rev-parse --show-toplevel) ] && cd $(git rev-parse --show-toplevel || pwd)''
La página del man
para git-config
(bajo Alias ) dice:
Si la expansión de alias tiene un prefijo con un signo de exclamación, se tratará como un comando de shell. [...] Tenga en cuenta que los comandos de shell se ejecutarán desde el directorio de nivel superior de un repositorio, que puede no ser necesariamente el directorio actual.
Entonces, en UNIX puedes hacer:
git config --global --add alias.root ''!pwd''
Para calcular la ruta absoluta del directorio raíz de git actual, digamos que para usar en un script de shell, use esta combinación de readlink y git rev-parse:
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdup
te da el número correcto de ".." s para llegar a la raíz desde tu cwd, o la cadena vacía si estás en la raíz. Luego, agregue "./" para tratar el caso de la cadena vacía y use readlink -f
para traducir a una ruta completa.
También puede crear un comando git-root
en su PATH como un script de shell para aplicar esta 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
(Lo anterior se puede pegar en un terminal para crear git-root y establecer los bits de ejecución; el script real está en las líneas 2, 3 y 4.)
Y luego podrías ejecutar git root
para obtener la raíz de tu árbol actual. Tenga en cuenta que en el script de shell, use "-e" para hacer que el shell se cierre si falla el rev-parse, de modo que pueda obtener correctamente el estado de salida y el mensaje de error si no está en un directorio git.
Para corregir la respuesta "git config" solo un poco:
git config --global --add alias.root ''!pwd -P''
y limpiar el camino. Muy agradable.
Para escribir una respuesta simple aquí, para que podamos usar
git root
para hacer el trabajo, simplemente configure su git usando
git config --global alias.root "rev-parse --show-toplevel"
y entonces es posible que desee agregar lo siguiente a su ~/.bashrc
:
alias cdroot=''cd $(git root)''
para que puedas usar cdroot
para ir a la parte superior de tu repositorio.
Sí:
git rev-parse --show-toplevel
Si está buscando un buen alias para hacer esto, no haga estallar el cd
si no está en un git dir:
alias ..g=''git rev-parse && cd "$(git rev-parse --show-cdup)"''
Si ya está en el nivel superior o no está en un repositorio de git, cd $(git rev-parse --show-cdup)
lo llevará a su casa (solo cd). cd ./$(git rev-parse --show-cdup)
es una forma de arreglar eso.
Tenía que resolver esto yo mismo hoy. Resuelto en C # como lo necesitaba para un programa, pero supongo que puede ser fácilmente reescrito. Considere este dominio 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;
}
Soluciones cortas que funcionan con submódulos, en ganchos y dentro del directorio .git
Aquí está la respuesta corta que la mayoría querrá:
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"
Esto funcionará en cualquier lugar del árbol de trabajo de git (incluido dentro del directorio .git
), pero se supone que los directorios del repositorio se llaman .git
(que es el valor predeterminado). Con los submódulos, esto irá a la raíz del repositorio más externo.
Si desea llegar a la raíz del submódulo actual use:
echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))
Para ejecutar fácilmente un comando en su raíz de submódulo, bajo [alias]
en su .gitconfig
, agregue:
sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec /"$@/"; }; f"
Esto te permite hacer cosas fácilmente como git sh ag <string>
Solución robusta que admite directorios con nombre diferente o externo .git
o $GIT_DIR
.
Tenga en cuenta que $GIT_DIR
puede apuntar a algún lugar externo (y no ser llamado .git
), de ahí la necesidad de una verificación adicional.
Pon esto en tu .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"
}
git_root
escribiendo git_root
(después de reiniciar su shell: exec bash
)
$ git config alias.root ''!pwd''
# then you have:
$ git root
alias git-root=''cd /`git rev-parse --git-dir/`; cd ..''
Todo lo demás falla en algún momento, ya sea yendo al directorio de inicio o simplemente falladamente. Esta es la forma más rápida y rápida de volver a GIT_DIR.