Kiểm tra xem thư mục hiện tại có phải là kho Git không


197

Tôi đang viết một loạt các kịch bản để quản lý Git trong zsh.

Làm cách nào để kiểm tra xem thư mục hiện tại có phải là kho Git không? (Khi tôi không ở trong repo Git, tôi không muốn thực thi một loạt các lệnh và nhận được một loạt các fatal: Not a git repositoryphản hồi).


Bạn đã xem tệp hoàn thành bash (trong contrib / xong / git-xong.bash) để tìm cảm hứng chưa? Tôi sử dụng lệnh __git_ps1 như một phần của dấu nhắc bash. Trong thực tế hầu hết nó sẽ nguồn trong zsh. Hàm __gitdir có lẽ là hàm bạn muốn.
jabbie

1
@jabbie: tại sao bạn không đưa ra câu trả lời?
amarillion

Bạn đã kiểm tra các chức năng đã có trong phân phối zsh chưa?
MBO


1
Lưu ý: không ai trong số các câu trả lời hiện tại xem xét việc $GIT_DIRhoặc $GIT_WORK_TREEmôi trường biến, hoặc làm thế nào họ tương tác với nhau.
o11c

Câu trả lời:


154

Sao chép từ tệp hoàn thành bash, sau đây là một cách ngây thơ để làm điều đó

# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
# Distributed under the GNU General Public License, version 2.0.

if [ -d .git ]; then
  echo .git;
else
  git rev-parse --git-dir 2> /dev/null;
fi;

Bạn có thể gói nó trong một hàm hoặc sử dụng nó trong một tập lệnh.

Ngưng tụ trong điều kiện một dòng thích hợp cho bashzsh

[ -d .git ] && echo .git || git rev-parse --git-dir > /dev/null 2>&1

3
@William Pursell Tại sao ngã ba khi bạn không cần? Chủ yếu cho tốc độ trong trường hợp tầm thường.
jabbie

16
Câu trả lời nên được cập nhật để sử dụng git rev-parse --is-inside-git-dir. Cá nhân tôi sử dụng git rev-parse --is-inside-work-treetrước khi đặt PS1 của tôi.
juliohm

11
@juliohm --is-inside-git-dirsẽ chỉ trả về true nếu bạn thực sự nằm trong .gitthư mục của kho lưu trữ. Tôi không nghĩ OP đang tìm kiếm điều đó.
nyuszika7h

7
Không --is-inside-work-treephải cũng --is-inside-git-dirsẽ không hoạt động khi bạn ở ngoài một repo git. xem: Groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fishingwebdev

7
Điều này sẽ thất bại nếu thư mục git là một cái gì đó khác .git. Đối với sự mạnh mẽ, bỏ qua [ -d .git ]và chỉ sử dụng git rev-parse ....
Peter John Acklam

133

Bạn có thể dùng:

git rev-parse --is-inside-work-tree

Nó sẽ in 'true' nếu bạn đang ở trong cây làm việc git repos.

Lưu ý rằng nó vẫn trả lại đầu ra cho STDERR nếu bạn ở ngoài git repo (và không in 'false').

Lấy từ câu trả lời này: https://stackoverflow.com/a/2044714/12983


Đây là cách đơn giản nhất để kiểm tra.
calbertts

3
Điều này vẫn sẽ in sai cho một kho lưu trữ trống không có cây hoạt động
noggin182

Điều này không xem xét thư mục con. Tôi cần phải xác minh làm git rev-parse --show-topleveltrận đấu với thư mục con tôi đang kiểm tra
Alper

Câu trả lời được chọn thậm chí không in ra bất cứ điều gì. Cái này làm việc
ScottyBlades

47

Sử dụng git rev-parse --git-dir

nếu git rev-parse --git-dir> / dev / null 2> & 1; sau đó
  : # Đây là kho git hợp lệ (nhưng hiện đang hoạt động
    # thư mục có thể không phải là cấp cao nhất.
    # Kiểm tra đầu ra của lệnh git rev-parse nếu bạn quan tâm)
khác
  : # đây không phải là kho git
fi


7

Không chắc chắn nếu có một cách truy cập / tài liệu công khai để làm điều này (có một số chức năng git nội bộ mà bạn có thể sử dụng / lạm dụng trong chính nguồn git)

Bạn có thể làm một cái gì đó như;

if ! git ls-files >& /dev/null; then
  echo "not in git"
fi

7

Dựa trên câu trả lời của @Alex Cory :

[ "$(git rev-parse --is-inside-work-tree 2>/dev/null)" == "true" ]

không chứa bất kỳ hoạt động dư thừa và hoạt động trong -echế độ.

  • Như @ go2null đã lưu ý , điều này sẽ không hoạt động trong một repo trần. Nếu bạn muốn làm việc với một repo trần vì bất kỳ lý do gì, bạn chỉ có thể kiểm tra git rev-parsethành công, bỏ qua đầu ra của nó.
    • Tôi không coi đây là một nhược điểm vì dòng trên được dành cho kịch bản và hầu như tất cả gitcác lệnh chỉ có giá trị trong một bảng công việc. Vì vậy, đối với các mục đích viết kịch bản, rất có thể bạn quan tâm đến việc không chỉ bên trong một "git repo" mà bên trong một bàn làm việc.

điều này thất bại bên trong một repo git trần
go2null

Thay vì kiểm tra đầu ra, tốt hơn là kiểm tra giá trị trả về. Đừng gọi [gì cả. Chỉ cần làm if git rev-parse --is-inside-work-tree; then ...(với chuyển hướng như mong muốn.)
William Pursell

1
@WilliamPursell kiểm tra giá trị thoát không hoạt động ở đây: stackoverflow.com/questions/2180270/iêu
ivan_pozdeev 7/2/19

@Ivan_pozdeev Phụ thuộc vào định nghĩa của bạn về "công việc". Trong trường hợp này, tôi sẽ nói rằng việc kiểm tra giá trị trả về không hoạt động, trong khi kiểm tra đầu ra thì không. Trong cả hai trường hợp, từ góc độ thực hành tốt nhất để viết mã trong trình bao, việc kiểm tra giá trị trả về sẽ phù hợp hơn.
William Pursell

@WilliamPursell nếu bạn đọc bình luận được liên kết, bạn sẽ biết ý của tôi là "không hoạt động" ở đây.
ivan_pozdeev

6

Một giải pháp khác là kiểm tra mã thoát của lệnh.

git rev-parse 2> /dev/null; [ $? == 0 ] && echo 1

Điều này sẽ in 1 nếu bạn đang ở trong thư mục kho git.


Lưu ý rằng điều này sẽ có RC 0 ngay cả khi bạn ở trong .gitthư mục - điều mà bạn có thể muốn hoặc không muốn.
ivan_pozdeev

Git được viết hoàn toàn để bạn có thể đóng các tệp bạn không muốn , git rev-parse 2>&-.
jthill

3

Câu trả lời này cung cấp hàm shell POSIX mẫu và ví dụ sử dụng để bổ sung cho câu trả lời của @ jabbie .

is_inside_git_repo() {
    git rev-parse --is-inside-work-tree >/dev/null 2>&1
}

gittrả về errorlevel 0nếu nó nằm trong kho git, nếu không nó sẽ trả về errorlevel 128. (Nó cũng trả về truehoặc falsenếu nó nằm trong kho git.)

Ví dụ sử dụng

for repo in *; do
    # skip files
    [ -d "$repo" ] || continue
    # run commands in subshell so each loop starts in the current dir
    (
        cd "$repo"
        # skip plain directories
        is_inside_git_repo || continue
        printf '== %s ==\n' "$repo"
        git remote update --prune 'origin' # example command
        # other commands here
    )
done

Không đủ. Bên trong .git, nó sẽ thành công nhưng in false.
ivan_pozdeev

@ivan_pozdeev: Nếu git rev-parse --is-inside-work-treetrả về truehoặc falsesau đó nó nằm trong repo git và đó là những gì hàm trả về. đó là, chức năng là chính xác
go2null

để mở rộng, xem mô tả trong câu trả lời, giá trị được trả về từ git bị bỏ qua, errorlevel là những gì được sử dụng.
go2null

2

cái này hiệu quả với tôi Bạn vẫn nhận được lỗi nhưng chúng đủ dễ để triệt tiêu. nó cũng hoạt động từ trong các thư mục con!

trạng thái git> / dev / null 2> & 1 && echo Xin chào thế giới!

Bạn có thể đặt điều này trong một câu lệnh if then nếu bạn cần điều kiện làm nhiều hơn.


2
Đủ tốt cho nhiều trường hợp có lẽ, nhưng nó thất bại trên một repo trần.
tự đại diện

3
git statuscó thể rất chậm trên một repo lớn / cũ. Tôi sẽ không sử dụng nó cho mục đích này.
henrebotha

1

Tại sao không sử dụng mã thoát? Nếu một kho git tồn tại trong thư mục hiện hành, sau đó git branchgit taglệnh trở lại mã trả về 0; nếu không, mã thoát khác không sẽ được trả về. Bằng cách này, bạn có thể xác định xem một kho git có tồn tại hay không. Đơn giản, bạn có thể chạy:

git tag > /dev/null 2>&1 && [ $? -eq 0 ]

Ưu điểm : Linh hoạt. Nó hoạt động cho cả kho lưu trữ trần và không trần, và trong sh, zsh và bash.

Giải trình

  1. git tag: Lấy thẻ của kho lưu trữ để xác định xem có tồn tại hay không.
  2. > /dev/null 2>&1: Ngăn chặn in bất cứ thứ gì, kể cả đầu ra bình thường và lỗi.
  3. [ $? -eq 0 ]: Kiểm tra xem lệnh trước có trả về với mã thoát 0 hay không. Như bạn có thể biết, mọi lối thoát khác không có nghĩa là có điều gì đó tồi tệ đã xảy ra. $?được mã lối ra của lệnh trước đó, và [, -eq]thực hiện các so sánh.

Ví dụ, bạn có thể tạo một tệp có tên check-git-repovới các nội dung sau, làm cho nó có thể thực thi được và chạy nó:

#!/bin/sh

if git tag > /dev/null 2>&1 && [ $? -eq 0 ]; then
    echo "Repository exists!";
else
    echo "No repository here.";
fi

0

# kiểm tra nếu git repo

if [ $(git rev-parse --is-inside-work-tree) = true ]; then
    echo "yes, is a git repo"
    git pull
else
    echo "no, is not a git repo"
    git clone url --depth 1
fi

Đây không phải là thực hành tốt nhất. Nếu chạy bên ngoài thư mục làm việc, bạn sẽ nhận được "fatal: not a git repository (hoặc bất kỳ thư mục mẹ nào): .git" được viết trên stderr và "không, không phải là git repo" trên thiết bị xuất chuẩn. Không cần phải gọi [ở đây cả. Chỉ cần làm:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell 7/2/19

Trong trường hợp của tôi, tôi cảm thấy thoải mái với điều này và tôi muốn theo dõi trục trặc này trong nhật ký của mình. Chúc mừng!
Pascal Andy

0
if ! [[ $(pwd) = *.git/* || $(pwd) = *.git ]]; then 
  if type -P git >/dev/null; then
    ! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
     printf '\n%s\n\n' "GIT repository detected." && git status
    }
  fi
fi

Cảm ơn bạn ivan_pozdeev , Bây giờ tôi có một bài kiểm tra nếu trong thư mục .git, mã sẽ không chạy nên không có lỗi được in ra hoặc tình trạng thoát sai.

Kiểm tra " ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " nếu bạn không ở trong .git repo thì nó sẽ chạy lệnh git. Lệnh loại dựng sẵn được sử dụng để kiểm tra xem bạn đã cài đặt git chưa hoặc nó nằm trong PATH của bạn. xem loại trợ giúp


0

Làm thế nào đây:

if git status -s 2>/dev/null;then
    echo "this is a git repo"
else
    echo "this is NOT a git repo"
fi

-1

Bạn có thể thêm hoặc thay thế $ PS1 trong zshrc của mình bằng một hoặc một công cụ nhắc nhở khác. Bằng cách này, bạn có thể được thông báo một cách thuận tiện cho dù bạn đang ở trong một repo git và trạng thái của repo.


3
Toàn bộ câu hỏi của OP là làm thế nào để thực hiện nó trong một kịch bản
Andrew C

và làm thế nào __git_ps1 không thể được sử dụng từ trong tập lệnh? Toàn bộ điểm của git-prompt là kiểm tra trạng thái git của thư mục hiện tại, đây là những gì đã được hỏi.
jxqz

-1
! git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { 
  printf '%s\n\n' "GIT repository detected." && git status
}

Các ! phủ nhận như vậy ngay cả khi bạn chạy nó trong một thư mục không phải là repo git, nó sẽ không cung cấp cho bạn một số lỗi nghiêm trọng

Các > / dev / null 2> & 1 sẽ gửi thông điệp đến / dev / null từ bạn ngay sau khi trạng thái thoát. Các {} là dành cho nhóm lệnh vì vậy tất cả các lệnh sau || sẽ chạy nếu git rev-parse thành công kể từ khi chúng tôi sử dụng a! trong đó phủ nhận trạng thái thoát của git rev-parse. Các printf là chỉ để in một số thông điệp và git status để in tình trạng của repo.

Gói nó trong một chức năng hoặc đặt nó trong một kịch bản. Hi vọng điêu nay co ich


1
Không đủ. Bên trong .git, nó sẽ thành công nhưng in false.
ivan_pozdeev
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.