web-dev-qa-db-ja.com

git:作業ツリーのルートに移動するクイックコマンド

単純なgitコマンドでリポジトリの「ルート」に移動する必要がありました。

スクリプトから始めましたが、シェルのActive Directoryを変更できないことがわかったので、関数を実行する必要がありました。残念ながら、たとえばダッシュ以外の形式の「git root」で直接呼び出すことはできません。

function git-root() {
 if [ -d .git ]; then
  return 0
 fi

 A=..
 while ! [ -d $A/.git ]; do 
  A="$A/.."
 done
 cd $A
}

より良い解決策はありますか? (関数はすぐに作成され、提案は大歓迎です)

40
elmarco

これは以前に尋ねられました 1つのコマンドでgitルートディレクトリを取得する方法はありますか? @docgnomeの回答をコピーすると、彼は書きます

cd $(git rev-parse --show-cdup)

必要に応じてエイリアスを作成します。

alias git-root='cd $(git rev-parse --show-cdup)'
56
Peter

さらに簡単に、 1つのコマンドでgitルートディレクトリを取得する方法はありますか? から盗み、(Peterの提案に従って)エイリアスを作成します。

cd "$(git rev-parse --show-toplevel)"

これは、ルートディレクトリにいるかどうかに関係なく機能します。

44
Chris Westin

上記のピーターの答えは、git rootのサブディレクトリにいる場合はうまくいきます。すでにgit rootにいる場合は、$ HOMEに戻ります。これを防ぐために、いくつかのbash条件を使用できます。

if [ "`git rev-parse --show-cdup`" != "" ]; then cd `git rev-parse --show-cdup`; fi

したがって、エイリアスは次のようになります。

alias git-root='if [ "`git rev-parse --show-cdup`" != "" ]; then cd `git rev-parse --show-cdup`; fi'
15
$ git config alias.root '!pwd'
$ git root
7
FractalSpace

残念ながら、現在のディレクトリの変更はシェルによってのみ実行でき、サブプロセスでは実行できません。 gitがコマンドの解析に取り掛かる頃には、もう手遅れです。gitはすでに別のプロセスで生成されています。

これは、本当に大規模な、テストされていないShell関数です。

function git() {
    if [ "$1" == "root" ]; then
        git-root
    else
        git "$@"
    fi
}
3
Josh Lee

サブモジュール、フック、および.gitディレクトリ内で機能する短いソリューション

以下は、ほとんどの人が望む短い回答です。

r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && cd "${r%%/.git/*}"

これはgit作業ツリー(.gitディレクトリ内を含む)のどこでも機能しますが、リポジトリディレクトリは.git(デフォルト)と呼ばれていると想定しています。サブモジュールの場合、これは最も外側の格納リポジトリのルートに移動します。

現在のサブモジュールのルートに到達したい場合は、以下を使用します。

cd ''$(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"
}

cd_git_rootと入力して実行します(シェルの再起動後:exec bash

3
Tom Hale

Bashとzshで機能するより良いエイリアスは次のとおりです。

alias git-root='cd "$(git rev-parse --show-cdup)"'
2
tasmo