Mercurialには(.hgを含む)ルートディレクトリを印刷する方法があります。
hg root
gitに.gitディレクトリを含むディレクトリを取得する同等のものはありますか?
bzr root
がバザーで
Mercurialには(.hgを含む)ルートディレクトリを印刷する方法があります。
hg root
gitに.gitディレクトリを含むディレクトリを取得する同等のものはありますか?
bzr root
がバザーで
回答:
はい:
git rev-parse --show-toplevel
Gitコマンドをより直接的に複製する場合は、エイリアスを作成できます。
git config --global alias.root 'rev-parse --show-toplevel'
そして今git root
はちょうど同じように機能しhg root
ます。
注:サブモジュールでは、親リポジトリではなく、サブモジュールのルートディレクトリが表示されます。Git> = 2.13以上を使用している場合、サブモジュールがスーパープロジェクトのルートディレクトリを表示できる方法があります。あなたのgitがそれより古い場合は、この別の答えを見てください。
git config --global alias.exec '!exec '
ようなことをできるように、私は常に定義していますgit exec make
。シェルエイリアスは常に最上位ディレクトリで実行されるため、これは機能します。
hg root
です。チェックアウトしたリポジトリの最上位ディレクトリを出力します。それはあなたをそれに切り替えません(そして、実際には、現在のディレクトリとシェルの全体の概念がどのように相互作用するかのために、そうすることはできませんでした)。
~/my.proj/foo/bar
、に~/my.proj
シンボリックリンクされている~/src/my.proj
場合、上記のコマンドでに移動します~/src/my.proj
。その後に何をしたいかがツリーにとらわれない場合、問題になる可能性があります。
.git
ディレクトリ内では機能しません。
(エイリアスの下の)のman
ページには次のように書かれています:git-config
エイリアス展開の前に感嘆符が付いている場合は、シェルコマンドとして扱われます。[...]シェルコマンドは、リポジトリの最上位ディレクトリから実行されることに注意してください。これは、必ずしも現在のディレクトリであるとは限りません。
したがって、UNIXでは次のことができます。
git config --global --add alias.root '!pwd'
.zshrc
、 `alias cg =" cd $(git root) "を定義すると、$()部分はソース時に評価され、常に〜/ dotfilesを指します。 。
た--show-toplevel
、ごく最近に追加されgit rev-parse
か、なぜ誰もそれを言及されていませんか?
git rev-parse
manページから:
--show-toplevel
Show the absolute path of the top-level directory.
git-rev-parse
-その名前がリビジョン仕様の処理に関するものであることを示唆しているからです。ところで、「パスが指定されていない場合、gitは現在の設定を出力します」のgit --work-tree
ような動作を見てうれしいgit --exec-path[=<path>]
です。少なくとも、IMO、それはそのような機能を探すための論理的な場所になるでしょう。
root = rev-parse --show-toplevel
gitconfigでエイリアスを設定できます。
git config --global alias.root "rev-parse --show-toplevel"
、それからgit root
その仕事をすることができるでしょう
git rev-parse --show-toplevel
は、サブモジュールで試したときに機能します。gitサブモジュールのルートディレクトリを出力します。それはあなたのために何を印刷しますか?
--show-cdup
に--show-top-level
2011年2月で(この答えは、提出された後)。
「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-解析マニュアルページ:
--git-dir
Show $GIT_DIR if defined else show the path to the .git directory.
このスクリプトで動作を確認できgit setup-sh
ます。
Git> = 2.13のサブモジュールフォルダーにいる場合は、次を使用します。
git rev-parse --show-superproject-working-tree
を使用git rev-parse --show-toplevel
している場合は、Git 2.25+(2020年第1四半期)を使用していることを確認してください。
.git
すでにルートディレクトリにいる場合の相対パスを提供するようです。(少なくとも、msysgitでは実行されます。)
すでにトップレベルにいるか、gitリポジトリにいない場合は、cd $(git rev-parse --show-cdup)
ホームに戻ります(cdのみ)。 cd ./$(git rev-parse --show-cdup)
それを修正する1つの方法です。
cd "$(git rev-parse --show-cdup)"
。これcd ""
は、戻るのではなく、どこにも行かないため機能します$HOME
。そして、スペースがあるものを出力する場合に備えて、とにかく$()呼び出しを引用符で囲むことをお勧めします(ただし、このコマンドはこの場合はそうではありません)。
$PWD
。この例では、gitのルートをの$PWD
代わりに解決しrealpath $PWD
ます。
現在のgitルートディレクトリの絶対パスを計算するには、たとえばシェルスクリプトで使用するには、次のreadlinkとgit rev-parseの組み合わせを使用します。
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdup
cwdからルートに到達するための正しい「..」の数、またはルートにいる場合は空の文字列を提供します。次に、「./」を先頭に追加して、空の文字列のケースを処理し、
readlink -f
して完全パスに変換します。
git-root
このテクニックを適用するシェルスクリプトとして、PATHにコマンドを作成することもできます。
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
して現在のツリーのルートを取得することができます。シェルスクリプトでは、「-e」を使用してrev-parseが失敗した場合にシェルを終了させ、gitディレクトリにいない場合に終了ステータスとエラーメッセージを適切に取得できることに注意してください。
"$(git rev-parse ...)"
ようなハックの代わりに常に使用します./$(git rev-parse ...)
。
他の人が指摘したように、ソリューションの中核はを使用することgit rev-parse --show-cdup
です。ただし、対処すべきエッジケースがいくつかあります。
cwdがすでに作業ツリーのルートである場合、コマンドは空の文字列を生成します。
実際には空の行が生成されますが、コマンド置換は末尾の改行を削除します。最終結果は空の文字列です。
ほとんどの回答では、./
出力が"./"
前に追加されるため、空の出力がに送られる前に出力が行われcd
ます。
GIT_WORK_TREEがcwdの親ではない場所に設定されている場合、出力は絶対パス名になる可能性があります。
./
この状況では、先頭に追加するのは間違っています。a ./
が絶対パスの前に付加されている場合、それは相対パスになります(cwdがシステムのルートディレクトリの場合、それらは同じ場所のみを参照します)。
出力には空白が含まれる場合があります。
これは実際には2番目のケースにのみ適用されますが、簡単な修正があります。コマンド置換(およびその後の値の使用)を二重引用符で囲みます。
他の回答が指摘しているように、私たちはできる cd "./$(git rev-parse --show-cdup)"
が、2番目のエッジケース(および二重引用符を省略した場合は3番目のエッジケース)で壊れます。
多くのシェルcd ""
は何もしないものとして扱うので、それらのシェルに対して実行できますcd "$(git rev-parse --show-cdup)"
(二重引用符は、最初のエッジの場合は空の文字列を引数として保護し、3番目のエッジの場合は空白を保持します)。POSIXはの結果を言いますcd ""
は指定されていないので、この仮定を行わないことをお勧めします。
上記のすべてのケースで機能するソリューションには、何らかのテストが必要です。明示的に行うと、次のようになります。
cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"
cd
最初のエッジケースでは行われません。
cd .
最初のエッジケースの実行が許容できる場合は、パラメーターの展開で条件を実行できます。
cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
git root
上記の答えが使用する "git config --global --add alias.root '!pwd'"とシェルエイリアスgitroot = 'cd 'を使用しないのはなぜですか?
サブモジュール、フック、および.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 <string>
異なる名前の、外部.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
(シェルを再起動した後:exec bash
)
(root=$(git rev-parse --git-dir)/ && cd ${root%%/.git/*} && git rev-parse && pwd)
ただし、これは$GIT_DIR
、以外の名前の外部sをカバーしません.git
git-extras
追加https://github.com/tj/git-extras/blob/master/Commands.md#git-rootを$ 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 ..'
その他のすべては、ホームディレクトリに移動するか、惨めに失敗するかのいずれかの時点で失敗します。これは、GIT_DIRに戻るための最速かつ最短の方法です。
$GIT_DIR
を使用して.git
workingtree から切り離されている場合、これは失敗しますgitdir: SOMEPATH
。その結果、これはサブモジュールの場合も失敗し$GIT_DIR
ます.git/modules/SUBMODULEPATH
。
以下は、両方のケースを処理するために私が作成したスクリプトです。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
)
うまくいけば、これは役に立ちます。
git exec
アイデアが裸のリポジトリでより役立つことに気付いたので、私は実際にトップの回答に賛成しました。ただし、この回答のこのスクリプトは、ベアケースと非ベアケースを正しく処理するため、誰かに役立つ可能性があるため、この回答はここに残します。
git submodule
が$GIT_DIR
含まれるs 内では失敗します/.git/modules/SUBMODULE
。また、あなたは、.git
ディレクトリが非ベアケースのワークツリーの一部であると仮定します。
$ git config alias.root '!pwd'
# then you have:
$ git root
[alias] findroot = "!f () { [[ -d ".git" ]] && echo "Found git in [
pwd ]" && exit 0; cd .. && echo "IN
pwd" && f;}; f"
git config --global alias.root '!pwd'
動作します。非グローバルバリアントとは異なる動作をするケースを見つけることができませんでした。(Unix、git 1.7.10.4)ところで:無限の再帰を避けるためにfindroot
が必要/.git
です。
Git 2.13.0以降、ルートプロジェクトのパスを表示する新しいオプションがサポートされています。これは、サブモジュール内から使用されている場合でも機能します。
git rev-parse --show-superproject-working-tree
シェルフレームワークを使用している場合、シェルエイリアスがすでに使用可能になっている可能性があります。
$ grt
OH-MY-zshの(68K) (cd $(git rev-parse --show-toplevel || echo ".")
)$ git-root
中prezto(8.8k) (ディスプレイ作業ツリーのルートへのパス)$ g..
zimfw(1k)(現在のディレクトリを作業ツリーの最上位に変更します。)Daniel Brockmanの優れたコメントをさらに詳しく説明したいと思います。
定義git config --global alias.exec '!exec '
すると、次のようなgit exec make
理由により、次のことが可能になりますman git-config
。
エイリアス展開の前に感嘆符が付いている場合は、シェルコマンドとして扱われます。[...]シェルコマンドは、リポジトリの最上位ディレクトリから実行されることに注意してください。これは、必ずしも現在のディレクトリであるとは限りません。
また、それ$GIT_PREFIX
がリポジトリのトップレベルのディレクトリを基準にした現在のディレクトリへのパスになることも知っておくと便利です。しかし、それが戦闘の半分に過ぎないことを知っている™。シェル変数展開では、使用がかなり難しくなります。だから私はそのように使うことを勧めbash -c
ます:
git exec bash -c 'ls -l $GIT_PREFIX'
他のコマンドは次のとおりです。
git exec pwd
git exec make
git
実行可能ファイルを必要とせずに誰かがこれを行うためのPOSIX準拠の方法を必要とする場合:
#$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
スクリプトの一部として機能が必要な場合は、シバンを削除し、最後のgit_root_recurse_parent
行を次のように置き換えます。
git_root() {
(git_root_recurse_parent)
}
if
ステートメントは、再帰でディレクトリを変更したかどうかをチェックすることになっています。それが同じディレクトリに残っている場合は、どこかにスタックしていると想定し(例/
:)、再帰を停止します。バグが修正され、期待どおりに動作するようになりました。指摘してくれてありがとう。
今日、これを自分で解決しなければなりませんでした。プログラムに必要なため、C#で解決しましたが、簡単に書き換えることができると思います。このパブリックドメインを検討してください。
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;
}