Có cách nào để lấy thư mục gốc git trong một lệnh không?


669

Mercurial có cách in thư mục gốc (có chứa .hg) thông qua

hg root

Có một cái gì đó tương đương trong git để có được thư mục chứa thư mục .git?


Kịch bản tốt Emil. Tôi cung cấp tập lệnh có sẵn trực tuyến và cho phép khả năng thêm tệp / thư mục làm đối số. github.com/Dieterbe/git-scripts/commit/ từ
Dieter_be

Ngoài ra, đối với bất kỳ ai tò mò hoặc tìm kiếm bzr rootđã được sử dụng rất nhiều trong Bazaar
Kristopher Ives

Vui lòng lưu ý 'gcd': Git-Aware 'cd' Liên quan đến gốc kho lưu trữ với tính năng tự động hoàn thành tại jeetworks.org/node/52 .
Micha Wiedenmann


1
@MichaWiedenmann: liên kết đã chết.
d33tah

Câu trả lời:


1111

Đúng:

git rev-parse --show-toplevel

Nếu bạn muốn sao chép lệnh Git trực tiếp hơn, bạn có thể tạo bí danh :

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

và bây giờ git rootsẽ hoạt động như hg root.


Lưu ý : Trong một submodule này sẽ hiển thị các thư mục gốc của submodulekhông kho mẹ. Nếu bạn đang sử dụng Git> = 2.13 trở lên, có một cách mà các mô hình con có thể hiển thị thư mục gốc của siêu dự án. Nếu git của bạn cũ hơn thế, hãy xem câu trả lời khác này.


147
Tôi luôn xác định git config --global alias.exec '!exec 'để tôi có thể làm những việc như thế git exec make. Điều này hoạt động vì các bí danh shell luôn được thực thi trong thư mục cấp cao nhất.
Daniel Brockman

8
Đây là những gì hg rootkhông. Nó in ra thư mục cấp cao nhất của kho lưu trữ đã kiểm tra của bạn. Nó không chuyển bạn sang nó (trên thực tế, nó không thể làm như vậy vì toàn bộ khái niệm thư mục hiện tại và shell của bạn tương tác như thế nào).
Omnifarious

14
Hãy cẩn thận với giải pháp này - nó sẽ theo dõi bất kỳ liên kết tượng trưng nào. Vì vậy, nếu bạn đang ở ~/my.proj/foo/bar~/my.projđược liên kết với nhau ~/src/my.proj, lệnh trên sẽ chuyển bạn đến ~/src/my.proj. Có thể là một vấn đề, nếu bất cứ điều gì bạn muốn làm sau đó không phải là bất khả tri.
Franci Penov

3
Làm thế nào tôi có thể sử dụng điều này từ trong một git hook? Cụ thể, tôi đang thực hiện một hook post-merge và tôi cần lấy thư mục gốc thực sự của repo git cục bộ.
Derek

12
Giải pháp này (và nhiều giải pháp khác trên trang này mà tôi đã thử) không hoạt động trong một git hook. Nói chính xác hơn, nó không hoạt động khi bạn ở trong .gitthư mục của dự án .
Dennis

97

Các mantrang cho git-config(dưới bí danh ) cho biết:

Nếu việc mở rộng bí danh được bắt đầu bằng dấu chấm than, nó sẽ được coi là lệnh shell. [...] Lưu ý rằng các lệnh shell sẽ được thực thi từ thư mục cấp cao nhất của kho lưu trữ, có thể không nhất thiết phải là thư mục hiện tại.

Vì vậy, trên UNIX bạn có thể làm:

git config --global --add alias.root '!pwd'

2
Vì vậy, nếu bạn có lệnh "git root", làm thế nào bạn có thể đặt nó trong bí danh? Nếu tôi đặt nó vào .zshrcvà tôi xác định `alias cg =" cd $ (git root) ", phần $ () được đánh giá tại thời gian nguồn và luôn trỏ đến ~ / dotfiles, vì đó là nơi zshrc của tôi .
zelk

2
@cormacrelf Bạn không đặt nó trong bí danh shell. Bạn có thể đặt nó trong một hàm shell hoặc script.
Conrad Meyer

4
@cormacrelf Đặt nó trong dấu ngoặc đơn thay vì dấu ngoặc kép, sau đó nó sẽ không được mở rộng tại thời điểm xác định, nhưng tại thời gian chạy.
clacke

3
@M cơ chế thực sự? Vì vậy, những gì bạn sẽ mong đợi nó để làm bên ngoài repo?
Alois Mahdal

1
@AloisMahdal thực sự đối với tôi nó không thất bại ngoài repo, nó chỉ đơn giản là báo cáo cwd.
justinpitts

90

Đã --show-toplevelchỉ gần đây đã được thêm vào git rev-parsehoặc tại sao không ai nhắc đến nó?

Từ git rev-parsetrang người đàn ông:

   --show-toplevel
       Show the absolute path of the top-level directory.

1
Cảm ơn đã chỉ ra điều này; không có sự giúp đỡ của bạn, thật khó để tôi đoán xem xét git-rev-parse- vì tên của nó cho thấy đó là về việc xử lý các thông số kỹ thuật sửa đổi. BTW, tôi rất vui khi thấy git --work-treecông việc tương tự như git --exec-path[=<path>]: "Nếu không có đường dẫn nào được đưa ra, git sẽ in cài đặt hiện tại"; ít nhất, IMO, đó là một nơi hợp lý để tìm kiếm một tính năng như vậy.
imz - Ivan Zakharyaschev

4
Đặc biệt, bạn có thể bí danh root = rev-parse --show-topleveltrong gitconfig của bạn.
Ốc cơ khí

2
nói cách khác, bạn có thể làm git config --global alias.root "rev-parse --show-toplevel"và sau đó git rootsẽ có thể thực hiện công việc
phân cực

@RyanTheLeach git rev-parse --show-toplevelhoạt động khi tôi thử nó trong một mô hình con. Nó in thư mục gốc của mô hình con git. Nó in gì cho bạn?
wvducky

2
Tôi đã bối rối tại sao câu trả lời này trùng lặp câu trả lời hàng đầu. Hóa ra câu trả lời hàng đầu đã được chỉnh sửa từ --show-cdupđến --show-top-leveltháng 2 năm 2011 (sau khi câu trả lời này được gửi).
wvducky

54

Thế còn " git rev-parse --git-dir"?

F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git

Các --git-dirtùy chọn dường như làm việc.

Từ trang hướng dẫn git rev-parse :

--git-dir

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

Bạn có thể thấy nó trong hành động trong git setup-shkịch bản này .

Nếu bạn đang ở trong thư mục mô hình con, với Git> = 2.13 , hãy sử dụng :

git rev-parse --show-superproject-working-tree

Nếu bạn đang sử dụng git rev-parse --show-toplevel, hãy chắc chắn rằng đó là với Git 2.25+ (Q1 2020) .


3
Đợi đã, nó đã gần nhưng nó nhận được .git dir thực tế, không phải là cơ sở của repo git. Ngoài ra, thư mục .git có thể ở nơi khác, vì vậy đây không phải là thứ tôi đang tìm kiếm chính xác.
wojo

2
Phải, tôi thấy bây giờ những gì bạn đang thực sự tìm kiếm. --show-cdup thì thích hợp hơn rồi. Tôi để lại câu trả lời của mình để minh họa sự khác biệt giữa hai lựa chọn.
VonC

2
Dường như lệnh này đưa ra một đường dẫn tương đối .gitnếu bạn đã ở trong thư mục gốc. (Ít nhất, nó hoạt động trên msysgit.)
Blair Holloway

2
+1, đây là câu trả lời duy nhất trả lời cho câu hỏi ban đầu "lấy thư mục chứa thư mục .git?", Thật thú vị khi thấy chính OP đề cập đến "thư mục .git có thể ở nơi khác".
FabienAndre

1
Đây là giải pháp duy nhất hoạt động trên windows VÀ cho kết quả có thể phân tích được khi sử dụng các mô đun con git (ví dụ: c: \ reporiesories \ myrepo \ .git \ module \ mysubmodule). Điều đó làm cho nó trở thành giải pháp mạnh mẽ nhất đặc biệt là trong một kịch bản có thể tái sử dụng.
chriskelly

36

Để viết một câu trả lời đơn giản ở đây, để chúng ta có thể sử dụng

git root

để thực hiện công việc, chỉ cần cấu hình git của bạn bằng cách sử dụng

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

và sau đó bạn có thể muốn thêm các mục sau vào ~/.bashrc:

alias cdroot='cd $(git root)'

để bạn có thể sử dụng cdrootđể đi đến đầu repo của bạn.


Rất đẹp! Cuối cùng thuận tiện!
cặn bã

Một câu trả lời tuyệt vời, cảm ơn bạn!
AVarf

26

Nếu bạn đã ở cấp cao nhất hoặc không có trong kho git cd $(git rev-parse --show-cdup)sẽ đưa bạn về nhà (chỉ cần cd). cd ./$(git rev-parse --show-cdup)là một cách để khắc phục điều đó.


7
Một lựa chọn khác là trích dẫn nó : cd "$(git rev-parse --show-cdup)". Điều này hoạt động bởi vì cd ""đưa bạn đến nơi, hơn là trở lại $HOME. Và dù sao đi nữa, đó là cách tốt nhất để trích dẫn các lệnh gọi $ (), trong trường hợp chúng xuất ra thứ gì đó có khoảng trắng (tuy nhiên không phải lệnh này sẽ trong trường hợp này).
ctrueden

Câu trả lời này hoạt động tốt ngay cả khi bạn thay đổi thư mục thành git repo thông qua liên kết tượng trưng . Một số ví dụ khác không hoạt động như mong đợi khi repo git của bạn ở dưới một liên kết tượng trưng vì chúng không giải quyết thư mục gốc của git liên quan đến bash $PWD. Ví dụ này sẽ giải quyết gốc của git $PWDthay vì realpath $PWD.
Damien Ó Ceallaigh

16

Để tính toán đường dẫn tuyệt đối của thư mục gốc git hiện tại, giả sử sử dụng trong tập lệnh shell, sử dụng kết hợp giữa readlink và git rev-parse:

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

git-rev-parse --show-cdupcung cấp cho bạn đúng số ".." để đến gốc từ cwd của bạn hoặc chuỗi trống nếu bạn ở gốc. Sau đó, trả trước "./" để xử lý trường hợp chuỗi trống và sử dụng readlink -fđể dịch sang đường dẫn đầy đủ.

Bạn cũng có thể tạo một git-rootlệnh trong PATH của mình dưới dạng tập lệnh shell để áp dụng kỹ thuật này:

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

(Phần trên có thể được dán vào một thiết bị đầu cuối để tạo git-root và thiết lập các bit thực thi; tập lệnh thực tế nằm trong các dòng 2, 3 và 4.)

Và sau đó bạn có thể chạy git rootđể lấy gốc của cây hiện tại của bạn. Lưu ý rằng trong tập lệnh shell, sử dụng "-e" để khiến trình bao thoát ra nếu phân tích cú pháp không thành công để bạn có thể nhận được đúng trạng thái thoát và thông báo lỗi nếu bạn không ở trong thư mục git.


2
Ví dụ của bạn sẽ bị hỏng nếu đường dẫn thư mục git "root" chứa khoảng trắng. Luôn luôn sử dụng "$(git rev-parse ...)"thay vì hack như ./$(git rev-parse ...).
Mikko Rantalainen

readlink -fkhông hoạt động giống nhau trên BSD. Xem SO này cho cách giải quyết. Câu trả lời Python có thể sẽ hoạt động mà không cần cài đặt bất cứ điều gì : python -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' "$(git rev-parse --show-cdup)".
Bluu

16

Như những người khác đã lưu ý, cốt lõi của giải pháp là sử dụng git rev-parse --show-cdup. Tuy nhiên, có một vài trường hợp cạnh để giải quyết:

  1. Khi cwd đã là gốc của cây làm việc, lệnh sẽ tạo ra một chuỗi rỗng.
    Trên thực tế, nó tạo ra một dòng trống, nhưng thay thế lệnh thoát khỏi ngắt dòng. Kết quả cuối cùng là một chuỗi rỗng.

    Hầu hết các câu trả lời đề nghị chuẩn bị đầu ra ./để đầu ra trống trở thành "./"trước khi được đưa vào cd.

  2. Khi GIT_WORK_TREE được đặt thành một vị trí không phải là cha mẹ của cwd, đầu ra có thể là một tên đường dẫn tuyệt đối.

    Chuẩn ./bị là sai trong tình huống này. Nếu a ./được thêm vào một đường dẫn tuyệt đối, nó sẽ trở thành một đường dẫn tương đối (và chúng chỉ tham chiếu đến cùng một vị trí nếu cwd là thư mục gốc của hệ thống).

  3. Đầu ra có thể chứa khoảng trắng.

    Điều này thực sự chỉ áp dụng trong trường hợp thứ hai, nhưng nó có một cách khắc phục dễ dàng: sử dụng dấu ngoặc kép xung quanh thay thế lệnh (và bất kỳ việc sử dụng tiếp theo nào của giá trị).

Như các câu trả lời khác đã lưu ý, chúng ta có thể làm cd "./$(git rev-parse --show-cdup)", nhưng điều này phá vỡ trong trường hợp cạnh thứ hai (và trường hợp cạnh thứ ba nếu chúng ta bỏ dấu ngoặc kép).

Nhiều shell được coi cd ""là không có op, vì vậy đối với các shell đó chúng ta có thể làm được cd "$(git rev-parse --show-cdup)"(dấu ngoặc kép bảo vệ chuỗi rỗng làm đối số trong trường hợp cạnh đầu tiên và giữ khoảng trắng trong trường hợp cạnh thứ ba). POSIX cho biết kết quả của cd ""là không xác định, vì vậy tốt nhất nên tránh đưa ra giả định này.

Một giải pháp hoạt động trong tất cả các trường hợp trên đòi hỏi một thử nghiệm nào đó. Hoàn thành rõ ràng, nó có thể trông như thế này:

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

Không cdđược thực hiện cho trường hợp cạnh đầu tiên.

Nếu nó được chấp nhận để chạy cd .cho trường hợp cạnh đầu tiên, thì điều kiện có thể được thực hiện trong việc mở rộng tham số:

cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"

Tại sao bạn không sử dụng "git config --global --add alias.root '! Pwd'" và một bí danh shell gitroot = 'cd git root' mà câu trả lời ở trên bạn sử dụng?
Jason Axelson

1
Sử dụng một bí danh có thể là không thể, ví dụ nếu bạn muốn kịch bản nó và không thể dựa vào bí danh tùy chỉnh.
xanh lam

1
Mô-đun phụ là một trường hợp góc khác.
Ryan The Leach

14

Chỉ trong trường hợp nếu bạn đang cho đường dẫn này đến chính Git, hãy sử dụng :/

# 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)

12

Các giải pháp ngắn hoạt động với mô hình con, trong hook và bên trong .gitthư mục

Đây là câu trả lời ngắn mà hầu hết sẽ muốn:

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

Điều này sẽ hoạt động ở bất cứ đâu trong cây làm việc git (bao gồm cả bên trong .gitthư mục), nhưng giả sử rằng (các) thư mục kho lưu trữ được gọi .git(là mặc định). Với các mô hình con, điều này sẽ đi đến thư mục gốc của kho chứa bên ngoài.

Nếu bạn muốn lấy gốc của mô hình con hiện tại, hãy sử dụng:

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

Để dễ dàng thực hiện một lệnh trong thư mục gốc submodule của bạn, dưới [alias]trong của bạn .gitconfig, add:

sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"

Điều này cho phép bạn dễ dàng làm những việc như git sh ag <string>

Giải pháp mạnh mẽ hỗ trợ tên khác nhau hoặc bên ngoài .githoặc $GIT_DIRthư mục.

Lưu ý rằng $GIT_DIRcó thể chỉ ra một nơi nào đó bên ngoài (và không được gọi .git), do đó cần phải kiểm tra thêm.

Đặt cái này trong .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"
}

Thực thi nó bằng cách gõ git_root(sau khi khởi động lại vỏ của bạn exec bash:)


Mã này đang được xem xét mã tại hàm bash Robust để tìm thư mục gốc của kho git . Nhìn vào đó để cập nhật.
Tom Hale

Đẹp. Phức tạp hơn những gì tôi đã đề xuất 7 năm trước ( stackoverflow.com/a/958125/6309 ), nhưng vẫn +1
VonC

1
Giải pháp ngắn hơn dọc theo các dòng đó là: (root=$(git rev-parse --git-dir)/ && cd ${root%%/.git/*} && git rev-parse && pwd)nhưng điều này không bao gồm các bên ngoài $GIT_DIRđược đặt tên khác.git
Tom Hale

Tôi tự hỏi nếu điều này có tính đến nhiều công việc hiện có thể có trong git 2.5+ ( stackoverflow.com/a/30185564/6309 )
VonC

Liên kết nhận xét của bạn đến "Chức năng bash mạnh mẽ để tìm gốc ..." hiện cung cấp 404.
ErikE

8

Để sửa đổi câu trả lời "git config" chỉ một chút:

git config --global --add alias.root '!pwd -P'

và làm sạch con đường. Rất đẹp.


7

Nếu bạn đang tìm kiếm một bí danh tốt để làm điều này cộng với việc không nổ tung cdnếu bạn không ở trong một git dir:

alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'


6

Bí danh shell này hoạt động cho dù bạn đang ở trong một tiểu thư git, hoặc ở cấp cao nhất:

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

cập nhật để sử dụng cú pháp hiện đại thay vì backticks:

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

5
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'

Mọi thứ khác đều thất bại vào một lúc nào đó hoặc vào thư mục chính hoặc thất bại thảm hại. Đây là cách nhanh nhất và ngắn nhất để quay lại GIT_DIR.


Có vẻ như 'git rev-parse --git-dir' là giải pháp sạch nhất.
Stablesog

3
Điều này không thành công, khi $GIT_DIRđược tách ra khỏi worktree bằng cách sử dụng .git-Files và gitdir: SOMEPATH. Do đó, điều này không thành công cho các mô hình con, nơi $GIT_DIRchứa .git/modules/SUBMODULEPATH.
Tino

5

Đây là tập lệnh mà tôi đã viết xử lý cả hai trường hợp: 1) kho lưu trữ với không gian làm việc, 2) kho lưu trữ trống.

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

git-root (tập tin thực thi trong đường dẫn của bạn):

#!/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
)

Hy vọng điều này là hữu ích.


1
Keith, cảm ơn bạn đã gợi ý, tôi đã bao gồm kịch bản.
jdsumsion

Tôi thực sự đã đưa ra câu trả lời hàng đầu bởi vì tôi nhận ra git execý tưởng này hữu ích hơn trong các kho lưu trữ không trần. Tuy nhiên, kịch bản này trong câu trả lời của tôi xử lý trường hợp trần so với không trần một cách chính xác, có thể được sử dụng cho ai đó, vì vậy tôi để câu trả lời này ở đây.
jdsumsion

1
Tuy nhiên điều này thất bại trong git submodules nơi $GIT_DIRchứa một cái gì đó như /.git/modules/SUBMODULE. Ngoài ra, bạn cho rằng, .gitthư mục là một phần của bàn làm việc trong trường hợp không trần.
Tino

4
$ git config alias.root '!pwd'
# then you have:
$ git root

Bí danh này sẽ thất bại như một toàn cầu. Sử dụng cái này thay thế (trong ~ / .gitconfig): [alias] findroot = "!f () { [[ -d ".git" ]] && echo "Found git in [pwd ]" && exit 0; cd .. && echo "IN pwd" && f;}; f"
FractalSpace

Tại sao downvote? Hãy làm nổi bật bất kỳ lỗi hoặc đề nghị cải thiện thay thế.
FractalSpace

1
Đối với tôi git config --global alias.root '!pwd'làm việc. Tôi không thể phát hiện ra bất kỳ trường hợp nào mà nó hoạt động khác với biến thể không toàn cầu. (Unix, git 1.7.10.4) BTW: Yêu findrootcầu của bạn /.gitđể tránh sự đệ quy vô tận.
Tino

4

Kể từ Git 2.13.0 , nó hỗ trợ một tùy chọn mới để hiển thị đường dẫn của dự án gốc, hoạt động ngay cả khi được sử dụng từ bên trong một mô hình con:

git rev-parse --show-superproject-working-tree

git-scm.com/docs/ . Hấp dẫn. Tôi đã phải bỏ lỡ thứ đó. +1
VonC

3
Mặc dù cảnh báo: "Không tạo ra kết quả nếu kho lưu trữ hiện tại không được sử dụng làm mô hình con bởi bất kỳ dự án nào."
VonC

Cảm ơn các bình luận! Tôi đã không nhận thấy điều đó.
Jordi Vilalta Prat

2

Bí danh Shell được cấu hình sẵn trong Shell Frameworks

Nếu bạn sử dụng khung shell, có thể đã có sẵn một bí danh shell:

  • $ grttrong oh-my-zsh (68k) ( cd $(git rev-parse --show-toplevel || echo "."))
  • $ git-roottrong prezto (8.8k) (hiển thị đường dẫn đến gốc cây làm việc)
  • $ g.. zimfw (1k) (thay đổi thư mục hiện tại thành cấp cao nhất của cây làm việc.)

1

Tôi muốn mở rộng dựa trên nhận xét tuyệt vời của Daniel Brockman.

Xác định git config --global alias.exec '!exec 'cho phép bạn làm những việc như git exec makebởi vì, như man git-configcác trạng thái:

Nếu việc mở rộng bí danh được bắt đầu bằng dấu chấm than, nó sẽ được coi là lệnh shell. [...] Lưu ý rằng các lệnh shell sẽ được thực thi từ thư mục cấp cao nhất của kho lưu trữ, có thể không nhất thiết phải là thư mục hiện tại.

Thật tiện lợi khi biết rằng đó $GIT_PREFIXsẽ là đường dẫn đến thư mục hiện tại so với thư mục cấp cao nhất của kho lưu trữ. Nhưng, biết nó chỉ là một nửa trận chiến ™. Shell mở rộng biến làm cho nó khá khó sử dụng. Vì vậy, tôi đề nghị sử dụng bash -cnhư vậy:

git exec bash -c 'ls -l $GIT_PREFIX'

các lệnh khác bao gồm:

git exec pwd
git exec make

1

Trong trường hợp bất cứ ai cũng cần một cách tuân thủ POSIX, mà không cần gitthực thi:

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

Nếu bạn chỉ muốn chức năng là một phần của tập lệnh, hãy xóa shebang và thay thế git_root_recurse_parentdòng cuối cùng bằng:

git_root() {
    (git_root_recurse_parent)
}

Hãy cẩn thận: Nếu điều này KHÔNG được gọi trong repo git thì đệ quy hoàn toàn không kết thúc.
AH

@AH ifCâu lệnh thứ hai được cho là để kiểm tra xem bạn đã thay đổi thư mục trong đệ quy chưa. Nếu nó vẫn nằm trong cùng thư mục, nó giả sử bạn bị kẹt ở đâu đó (ví dụ /) và đệ quy phanh. Lỗi đã được sửa, và bây giờ sẽ hoạt động như mong đợi. Cảm ơn đã chỉ ra điều đó.
swalog

0

Phải tự mình giải quyết chuyện này hôm nay. Đã giải quyết nó trong C # khi tôi cần nó cho một chương trình, nhưng tôi đoán nó có thể được viết lại một cách thực sự. Hãy xem xét miền công cộng này.

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;

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.