Periksa apakah direktori saat ini adalah repositori Git


197

Saya menulis serangkaian skrip untuk manajemen Git di zsh.

Bagaimana saya memeriksa apakah direktori saat ini adalah repositori Git? (Ketika saya tidak dalam repo Git, saya tidak ingin menjalankan banyak perintah dan mendapatkan banyak fatal: Not a git repositorytanggapan).


Sudahkah Anda melihat file bash completion (di contrib / completion / git-completion.bash) untuk mencari inspirasi? Saya menggunakan perintah __git_ps1 sebagai bagian dari bash prompt saya. Bahkan sebagian besar akan bersumber dalam zsh. Fungsi __gitdir mungkin adalah yang Anda inginkan.
jabbie

1
@ Jabbie: mengapa Anda tidak membuat jawaban itu?
amarillion

Sudahkah Anda memeriksa fungsi yang sudah dalam distribusi zsh?
MBO


1
Catatan: tidak ada jawaban saat ini yang mempertimbangkan variabel $GIT_DIRatau $GIT_WORK_TREElingkungan, atau bagaimana mereka berinteraksi.
o11c

Jawaban:


154

Disalin dari file penyelesaian bash, berikut ini adalah cara naif untuk melakukannya

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

Anda bisa membungkusnya dalam suatu fungsi atau menggunakannya dalam skrip.

Dikondensasi menjadi kondisi satu baris yang cocok untuk bash dan zsh

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

3
@ William Pursell Mengapa bercabang saat Anda tidak perlu? Terutama untuk kecepatan dalam kasus sepele.
jabbie

16
Jawabannya harus diperbarui untuk digunakan git rev-parse --is-inside-git-dir. Saya pribadi menggunakan git rev-parse --is-inside-work-treesebelum mengatur PS1 saya.
juliohm

11
@juliohm --is-inside-git-dirhanya akan mengembalikan true jika Anda benar-benar berada di dalam .gitdirektori repositori. Saya tidak berpikir OP mencari itu.
nyuszika7h

7
Juga --is-inside-work-treetidak --is-inside-git-dirakan bekerja ketika Anda berada di luar git repo. lihat: groups.google.com/forum/#!topic/git-users/dWc23LFhWxE
fisherwebdev

7
Ini akan gagal jika direktori git bukan sesuatu yang lain .git. Untuk ketahanan, abaikan [ -d .git ]dan gunakan saja git rev-parse ....
Peter John Acklam

133

Kamu bisa memakai:

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

Yang akan mencetak 'true' jika Anda berada di pohon kerja git repos.

Perhatikan bahwa masih mengembalikan output ke STDERR jika Anda berada di luar git repo (dan tidak mencetak 'false').

Diambil dari jawaban ini: https://stackoverflow.com/a/2044714/12983


Ini adalah cara paling sederhana untuk memeriksanya.
calbertts

3
Ini masih akan mencetak false untuk repositori kosong yang tidak memiliki
struktur

Ini tidak mempertimbangkan sub-direktori. Saya perlu memverifikasi apakah git rev-parse --show-toplevelcocok dengan subfolder yang saya periksa
alper

Jawaban yang dipilih bahkan tidak mencetak apa pun. Yang ini berhasil.
ScottyBlades

47

Gunakan git rev-parse --git-dir

jika git rev-parse --git-dir> / dev / null 2> & 1; kemudian
  : # Ini adalah repositori git yang valid (tetapi saat ini berfungsi
    Direktori # mungkin bukan level teratas.
    # Periksa output dari perintah git rev-parse jika Anda peduli)
lain
  : # ini bukan repositori git
fi


7

Tidak yakin apakah ada cara yang dapat diakses publik / didokumentasikan untuk melakukan ini (ada beberapa fungsi git internal yang dapat Anda gunakan / penyalahgunaan dalam sumber git itu sendiri)

Anda bisa melakukan sesuatu seperti;

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

7

Berdasarkan jawaban @Alex Cory :

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

tidak mengandung operasi yang berlebihan dan berfungsi dalam -emode.

  • Seperti @ go2null catat , ini tidak akan bekerja dalam repo kosong. Jika Anda ingin bekerja dengan repo kosong untuk alasan apa pun, Anda bisa mengecek git rev-parseberhasil, mengabaikan hasilnya.
    • Saya tidak menganggap ini sebagai kelemahan karena baris di atas digunakan untuk skrip, dan hampir semua gitperintah hanya valid di dalam worktree. Jadi untuk tujuan skrip, Anda kemungkinan besar tertarik bukan hanya di dalam "git repo" tetapi di dalam sebuah worktree.

ini gagal di dalam repo telanjang
go2null

Daripada memeriksa output, lebih baik praktik untuk memeriksa nilai kembali. Jangan memohon [sama sekali. Lakukan saja if git rev-parse --is-inside-work-tree; then ...(dengan pengalihan yang diinginkan.)
William Pursell

1
@WilliamPursell memeriksa nilai keluar tidak berfungsi di sini: stackoverflow.com/questions/2180270/…
ivan_pozdeev

@Ivan_pozdeev Tergantung pada definisi Anda tentang "bekerja". Dalam hal ini, saya akan mengatakan bahwa memeriksa nilai kembali tidak berfungsi, sementara memeriksa hasilnya tidak. Dalam kedua kasus, dari perspektif praktik terbaik untuk menulis kode di shell, lebih tepat untuk memeriksa nilai kembali.
William Pursell

@WilliamPursell jika Anda membaca komentar yang tertaut, Anda akan tahu apa yang saya maksud dengan "tidak bekerja" di sini.
ivan_pozdeev

6

Solusi lain adalah memeriksa kode keluar perintah.

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

Ini akan mencetak 1 jika Anda berada di folder repositori git.


Perhatikan bahwa ini akan memiliki rc 0 bahkan jika Anda berada di dalam .gitdirektori - yang mungkin atau tidak Anda inginkan.
ivan_pozdeev

Git ditulis dengan baik sehingga Anda bisa menutup file yang tidak Anda inginkan git rev-parse 2>&-,.
jthill

3

Jawaban ini memberikan contoh fungsi shell POSIX dan contoh penggunaan untuk melengkapi jawaban @ jabbie .

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

gitmengembalikan errorlevel 0jika berada di dalam repositori git, jika tidak maka akan mengembalikan errorlevel 128. (Ini juga mengembalikan trueatau falsejika ada di dalam repositori git.)

Contoh penggunaan

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

Tidak cukup. Di dalam .git, itu akan berhasil tetapi cetak false.
ivan_pozdeev

@ivan_pozdeev: Jika git rev-parse --is-inside-work-treekembali trueatau falsekemudian itu ada di dalam git repo, dan itulah fungsi yang dikembalikan. artinya, fungsinya benar
go2null

untuk memperluas, lihat deskripsi dalam jawaban, nilai yang dikembalikan dari git diabaikan, tingkat kesalahan adalah apa yang digunakan.
go2null

2

ini bekerja untuk saya. Anda masih mendapatkan kesalahan tetapi cukup mudah untuk ditekan. itu juga bekerja dari dalam subfolder!

status git> / dev / null 2> & 1 && gema Hello World!

Anda dapat memasukkan ini ke dalam pernyataan if lalu jika Anda perlu melakukan lebih banyak persyaratan.


2
Cukup bagus untuk banyak kasus mungkin, tetapi gagal pada repo telanjang.
Wildcard

3
git statusbisa sangat lambat pada repo besar / lama. Saya tidak akan menggunakannya untuk tujuan ini.
henrebotha

1

Mengapa tidak menggunakan kode keluar? Jika repositori git ada di direktori saat ini, maka git branchdan git tagperintah mengembalikan kode keluar dari 0; jika tidak, kode keluar yang tidak nol akan dikembalikan. Dengan cara ini, Anda dapat menentukan apakah repositori git ada atau tidak. Cukup, Anda dapat menjalankan:

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

Keuntungan : Flexibe. Ia bekerja untuk repositori telanjang dan non-telanjang, dan di sh, zsh dan bash.

Penjelasan

  1. git tag: Mendapatkan tag dari repositori untuk menentukan apakah ada atau tidak.
  2. > /dev/null 2>&1: Mencegah dari mencetak apa pun, termasuk output normal dan kesalahan.
  3. [ $? -eq 0 ]: Periksa apakah perintah sebelumnya dikembalikan dengan kode keluar 0 atau tidak. Seperti yang Anda ketahui, setiap jalan keluar yang tidak nol berarti sesuatu yang buruk terjadi. $?mendapatkan kode keluar dari perintah sebelumnya, dan [, -eqdan ]melakukan perbandingan.

Sebagai contoh, Anda dapat membuat file bernama check-git-repodengan konten berikut, membuatnya dapat dieksekusi dan menjalankannya:

#!/bin/sh

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

0

# periksa apakah 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

Ini bukan praktik terbaik. Jika dijalankan di luar direktori kerja, Anda akan mendapatkan "fatal: bukan repositori git (atau direktori induk mana pun): .git" ditulis di stderr, dan "tidak, bukan repo git" di stdout. Tidak perlu memohon [di sini sama sekali. Lakukan saja:if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then ....
William Pursell

Dalam kasus saya, saya nyaman dengan ini, dan saya ingin melacak kesalahan ini di log saya. Bersulang!
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

Terima kasih ivan_pozdeev , Sekarang saya memiliki tes jika di dalam direktori .git kode tidak akan berjalan sehingga tidak ada kesalahan yang dicetak atau status keluar salah.

" ! [[$ (Pwd) = .git / || $ (pwd) = * .git]] " menguji jika Anda tidak berada di dalam repo .git maka ia akan menjalankan perintah git. Perintah tipe builtin digunakan untuk memeriksa apakah Anda telah menginstal git atau masih dalam PATH Anda. lihat jenis bantuan


0

Bagaimana dengan ini:

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

-1

Anda dapat menambah atau mengganti $ PS1 Anda di zshrc Anda dengan satu atau beberapa alat git-prompt lainnya. Dengan cara ini Anda dapat dengan mudah mengetahui apakah Anda berada dalam git repo dan status repo itu ada.


3
Seluruh pertanyaan OP adalah bagaimana melakukannya dari dalam naskah
Andrew C

dan bagaimana __git_ps1 tidak dapat digunakan dari dalam skrip? Inti dari git-prompt adalah untuk memeriksa status git dari direktori saat ini, yang diminta.
jxqz

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

Itu! Meniadakan jadi bahkan jika Anda menjalankan ini di direktori yang bukan repo git itu tidak akan memberi Anda beberapa kesalahan fatal

The > / dev / null 2> & 1 mengirim pesan ke / dev / null karena Anda baru saja keluar dari status keluar. The {} adalah untuk pengelompokan perintah sehingga semua perintah setelah || akan berjalan jika git rev-parse berhasil karena kita menggunakan a! yang meniadakan status keluar dari git rev-parse. The printf hanya untuk mencetak beberapa pesan dan git status mencetak status repo.

Bungkus dalam suatu fungsi atau letakkan dalam naskah. Semoga ini membantu


1
Tidak cukup. Di dalam .git, itu akan berhasil tetapi cetak false.
ivan_pozdeev
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.