Mercurial a le moyen d’imprimer le répertoire racine (qui contient .hg) via
hg root
Y at-il quelque chose d’équivalent dans git pour obtenir le répertoire qui contient le répertoire .git?
Oui:
git rev-parse --show-toplevel
Remarque : Dans un sous-module, cela affichera le répertoire racine du sous-module et non le référentiel parent.
La page man
pour git-config
(sous Alias ) dit:
Si le développement de l'alias est précédé d'un point d'exclamation, il sera traité comme un shell commander. [...] Notez que Shell les commandes seront exécutées à partir du répertoire de niveau supérieur d'un référentiel, ce qui peut ne pas être le cas être nécessairement le répertoire en cours.
Donc, sous UNIX, vous pouvez faire:
git config --global --add alias.root '!pwd'
Est-ce que --show-toplevel
a été ajouté récemment à git rev-parse
ou pourquoi personne ne le mentionne?
De la page de manuel git rev-parse
:
--show-toplevel
Show the absolute path of the top-level directory.
Que diriez-vous de "git rev-parse --git-dir
"?
F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git
L'option --git-dir
semble fonctionner.
De page de manuel de git rev-parse :
--git-dir
Show $GIT_DIR if defined else show the path to the .git directory.
Vous pouvez le voir en action dans ce script git setup-sh
.
Si vous êtes dans un dossier de sous-modules, avec Git 2.20, utilisez :
git rev-parse --show-superproject-working-tree
Pour écrire une réponse simple ici, afin que nous puissions utiliser
git root
pour faire le travail, configurez simplement votre git en utilisant
git config --global alias.root "rev-parse --show-toplevel"
et ensuite vous voudrez peut-être ajouter ce qui suit à votre ~/.bashrc
:
alias cdroot='cd $(git root)'
afin que vous puissiez simplement utiliser cdroot
pour aller au sommet de votre repo.
Si vous êtes déjà au niveau supérieur ou non dans un référentiel git, cd $(git rev-parse --show-cdup)
vous ramènera à la maison (cd uniquement). cd ./$(git rev-parse --show-cdup)
est un moyen de résoudre ce problème.
Pour calculer le chemin absolu du répertoire racine git actuel, par exemple pour une utilisation dans un script Shell, utilisez cette combinaison de readlink et de git rev-parse:
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdup
vous donne le bon nombre de ".." à obtenirà la racine depuis votre cwd, ou la chaîne vide si vous êtes à la racine . Puis ajoutez "./" pour ajouter la chaîne vide case et utilisez readlink -f
pour traduire en chemin complet.
Vous pouvez également créer une commande git-root
dans votre PATH en tant que script Shell pour appliquer cette technique:
cat > ~/bin/git-root << EOF
#!/bin/sh -e
cdup=$(git rev-parse --show-cdup)
exec readlink -f ./$cdup
EOF
chmod 755 ~/bin/git-root
(Ce qui précède peut être collé dans un terminal pour créer git-root et définir des bits d’exécution; le script réel se trouve aux lignes 2, 3 et 4.)
Ensuite, vous pourrez exécuter git root
pour obtenir la racine de votre arborescence actuelle . Notez que dans le script Shell, utilisez "-e" pour que le shell se ferme en cas d’échec de l’analyse du rev afin de pouvoir Obtenez correctement le statut de sortie et le message d'erreur si vous ne vous trouvez pas dans un répertoire git.
Comme d'autres l'ont noté, le cœur de la solution consiste à utiliser git rev-parse --show-cdup
. Cependant, il existe quelques cas Edge à traiter:
Lorsque cwd est déjà la racine de l’arbre de travail, la commande génère une chaîne vide.
En réalité, il génère une ligne vide, mais la substitution de commande supprime le saut de ligne de fin. Le résultat final est une chaîne vide.
La plupart des réponses suggèrent de préfixer la sortie avec ./
de sorte qu'une sortie vide devienne "./"
avant qu'elle soit transmise à cd
.
Lorsque GIT_WORK_TREE est défini sur un emplacement autre que le parent du cwd, la sortie peut être un chemin absolu.
Le préfixe ./
est incorrect dans cette situation. Si un ./
est ajouté au début à un chemin absolu, il devient un chemin relatif (et ils ne font référence au même emplacement que si cwd est le répertoire racine du système).
La sortie peut contenir des espaces.
Cela ne s'applique vraiment que dans le second cas, mais la solution est simple: utilisez des guillemets autour de la substitution de commande (et de toute utilisation ultérieure de la valeur).
Comme d'autres réponses l'ont noté, nous pouvons faire cd "./$(git rev-parse --show-cdup)"
, mais cela casse dans le deuxième cas Edge (et le troisième cas Edge si nous omettons les guillemets doubles).
De nombreux shells considèrent cd ""
comme un no-op, nous pouvons donc utiliser cd "$(git rev-parse --show-cdup)"
(les guillemets doubles protègent la chaîne vide en tant qu'argument dans le premier cas Edge et préservent les espaces dans le troisième cas Edge). POSIX dit que le résultat de cd ""
n'est pas spécifié, il est donc préférable d'éviter cette hypothèse.
Une solution qui fonctionne dans tous les cas ci-dessus nécessite un test quelconque. Fait explicitement, cela pourrait ressembler à ceci:
cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"
Aucune cd
n'est faite pour le premier cas Edge.
S'il est acceptable d'exécuter cd .
pour le premier cas Edge, la condition est possible dans le développement du paramètre:
cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
Juste au cas où si vous fournissez ce chemin au Git lui-même, utilisez :/
# 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)
Solutions courtes fonctionnant avec des sous-modules, dans des crochets et dans le répertoire .git
Voici la réponse courte que la plupart voudront:
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"
Cela fonctionnera n'importe où dans un arbre de travail git (y compris à l'intérieur du répertoire .git
), mais supposons que le (s) répertoire (s) du référentiel s'appelle .git
(par défaut). Avec les sous-modules, cela ira à la racine du référentiel contenant le plus externe.
Si vous voulez aller à la racine de l'utilisation actuelle du sous-module:
echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))
Pour exécuter facilement une commande dans la racine de votre sous-module, sous [alias]
dans votre .gitconfig
, ajoutez:
sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"
Cela vous permet de faire facilement des choses comme git sh ag <string>
Solution robuste prenant en charge les répertoires .git
ou $GIT_DIR
portant un nom différent ou externes.
Notez que $GIT_DIR
peut pointer quelque part vers l'extérieur (et ne pas s'appeler .git
), d'où la nécessité d'une vérification supplémentaire.
Mettez ceci dans votre .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"
}
Exécutez-le en tapant git_root
(après avoir redémarré votre shell: exec bash
)
Pour modifier la "configuration de git", répondez un peu:
git config --global --add alias.root '!pwd -P'
et faire le chemin nettoyé. Très agréable.
Si vous cherchez un bon alias pour le faire, ne pas exploser cd
si vous n'êtes pas dans un répertoire git
alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'
Cet alias Shell fonctionne que vous soyez dans un sous-répertoire git ou au niveau supérieur:
alias gr='[ ! -z `git rev-parse --show-toplevel` ] && cd `git rev-parse --show-toplevel || pwd`'
mis à jour pour utiliser la syntaxe moderne au lieu de backticks:
alias gr='[ ! -z $(git rev-parse --show-toplevel) ] && cd $(git rev-parse --show-toplevel || pwd)'
Voici un script que j'ai écrit qui traite les deux cas: 1) un référentiel avec un espace de travail, 2) un référentiel nu.
https://Gist.github.com/jdsumsion/6282953
git-root
(fichier exécutable dans votre chemin):
#!/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
)
J'espère que cela est utile.
git-extras
ajoute $ git root
voir 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
$ brew install git-extras
$ apt-get install git-extras
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'
Tout le reste échoue à un moment donné, que ce soit dans le répertoire de base ou simplement en échec lamentable. C'est le moyen le plus rapide et le plus rapide de retourner à GIT_DIR.
$ git config alias.root '!pwd'
# then you have:
$ git root
Depuis Git 2.13.0 , il prend en charge une nouvelle option permettant d’afficher le chemin du projet racine, qui fonctionne même lorsqu’il est utilisé depuis un sous-module:
git rev-parse --show-superproject-working-tree
J'ai dû résoudre ce problème moi-même aujourd'hui. Résolu en C # car j'en avais besoin pour un programme, mais je suppose que ça peut être facilement réécrit. Considérez ce domaine public.
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;
}
Si quelqu'un a besoin d'un moyen conforme à POSIX pour le faire, sans l'exécutable git
:
git-root
:
#$1: Path to child directory
git_root_recurse_parent() {
# Check if cwd is a git root directory
if [ -d .git/objects -a -d .git/refs -a -f .git/HEAD ] ; then
pwd
return 0
fi
# Check if recursion should end (typically if cwd is /)
if [ "${1}" = "$(pwd)" ] ; then
return 1
fi
# Check parent directory in the same way
local cwd=$(pwd)
cd ..
git_root_recurse_parent "${cwd}"
}
git_root_recurse_parent
Si vous souhaitez simplement que la fonctionnalité fasse partie d'un script, supprimez Shebang et remplacez la dernière ligne git_root_recurse_parent
par:
git_root() {
(git_root_recurse_parent)
}
Si vous utilisez un framework Shell, il est possible qu'un alias Shell soit déjà disponible:
$ grt
dans oh-my-zsh (68k) (cd $(git rev-parse --show-toplevel || echo ".")
)$ git-root
dans prezto (8.8k) (affiche le chemin d'accès à la racine de l'arbre de travail)$ g..
zimfw (1k) (modifie le répertoire actuel au niveau supérieur de l'arbre de travail.)Je voulais développer l'excellent commentaire de Daniel Brockman.
Définir git config --global alias.exec '!exec '
vous permet de faire des choses comme git exec make
car, en tant que man git-config
, vous indiquez:
Si le développement de l'alias est précédé d'un point d'exclamation, il sera traité comme une commande Shell. [...] Notez que les commandes Shell seront exécutées à partir du répertoire de niveau supérieur d'un référentiel, qui ne correspond pas nécessairement au répertoire actuel.
Il est également utile de savoir que $GIT_PREFIX
sera le chemin du répertoire actuel par rapport au répertoire de niveau supérieur d'un référentiel. Mais, sachant que ce n’est que la moitié de la bataille ™. L'expansion variable de Shell le rend plutôt difficile à utiliser. Je suggère donc d'utiliser bash -c
comme suit:
git exec bash -c 'ls -l $GIT_PREFIX'
les autres commandes comprennent:
git exec pwd
git exec make