Periksa apakah diperlukan tarikan di Git

623

Bagaimana saya memeriksa apakah repositori jarak jauh telah berubah dan saya perlu menarik?

Sekarang saya menggunakan skrip sederhana ini:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

Tapi ini agak berat.

Apakah ada cara yang lebih baik? Solusi ideal akan memeriksa semua cabang jarak jauh, dan mengembalikan nama cabang yang diubah dan jumlah komit baru di masing-masing cabang.

takeshin
sumber
14
Harap dicatat: "git pull --dry-run" tidak berfungsi seperti yang diharapkan. Tampaknya, git pull melewati opsi yang tidak diketahui secara langsung untuk mengambil git. Hasilnya adalah tarikan git normal.
27
"pull" hanyalah cara singkat untuk melakukan "fetch" dan "merge" sekaligus, jika Anda perlu memeriksa status repo jarak jauh, Anda benar-benar mensimulasikan "fetch". Jadi git fetch -v --dry-runapa yang kamu butuhkan.
Claudio Floreani

Jawaban:

859

Pertama kali digunakan git remote update, untuk memperbaharui referensi jarak jauh Anda. Maka Anda dapat melakukan salah satu dari beberapa hal, seperti:

  1. git status -unoakan memberi tahu Anda apakah cabang yang Anda lacak ada di depan, di belakang atau telah menyimpang. Jika tidak mengatakan apa-apa, lokal dan remote adalah sama.

  2. git show-branch *masterakan menunjukkan kepada Anda komit di semua cabang yang namanya berakhiran 'master' (mis. master dan asal / master ).

Jika Anda menggunakan -vdengan git remote update( git remote -v update) Anda dapat melihat cabang mana yang diperbarui, sehingga Anda tidak benar-benar membutuhkan perintah lebih lanjut.

Namun, sepertinya Anda ingin melakukan ini dalam skrip atau program dan berakhir dengan nilai true / false. Jika demikian, ada cara untuk memeriksa hubungan antara komit HEAD Anda saat ini dan kepala cabang yang Anda lacak, meskipun karena ada empat kemungkinan hasil yang Anda tidak bisa menguranginya menjadi jawaban ya / tidak. Namun, jika Anda siap untuk melakukannya pull --rebasemaka Anda dapat memperlakukan "lokal ada di belakang" dan "lokal telah menyimpang" sebagai "perlu menarik", dan dua lainnya sebagai "tidak perlu menarik".

Anda bisa mendapatkan id komit dari setiap referensi yang menggunakan git rev-parse <ref>, sehingga Anda bisa melakukan ini untuk master dan origin / master dan membandingkannya. Jika mereka sama, cabang-cabangnya sama. Jika mereka tidak setara, Anda ingin tahu yang di depan yang lain. Menggunakan git merge-base master origin/masterakan memberi tahu Anda nenek moyang yang sama dari kedua cabang, dan jika mereka tidak menyimpang ini akan sama dengan yang satu atau yang lainnya. Jika Anda mendapatkan tiga id berbeda, cabang-cabangnya telah berbeda.

Untuk melakukan ini dengan benar, misalnya dalam skrip, Anda harus dapat merujuk ke cabang saat ini, dan cabang jarak jauh yang dilacaknya. Fungsi bash prompt-setting di /etc/bash_completion.dmemiliki beberapa kode yang berguna untuk mendapatkan nama cabang. Namun, Anda mungkin sebenarnya tidak perlu mendapatkan namanya. Git memiliki beberapa singkatan yang rapi untuk merujuk pada cabang dan komitmen (seperti yang didokumentasikan dalam git rev-parse --help). Secara khusus, Anda dapat menggunakan @untuk cabang saat ini (dengan asumsi Anda tidak berada dalam keadaan kepala terpisah) dan @{u}untuk cabang hulu (misalnya origin/master). Jadi git merge-base @ @{u}akan mengembalikan (hash dari) komit di mana cabang saat ini dan hulu berbeda dan git rev-parse @dan git rev-parse @{u}akan memberi Anda hash dari dua tips. Ini dapat diringkas dalam skrip berikut:

#!/bin/sh

UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")

if [ $LOCAL = $REMOTE ]; then
    echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
    echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
    echo "Need to push"
else
    echo "Diverged"
fi

Catatan: git versi lama tidak mengizinkannya @sendiri, jadi Anda mungkin harus menggunakannya @{0}.

Jalur ini UPSTREAM=${1:-'@{u}'}memungkinkan Anda untuk secara opsional melewati cabang upstream secara eksplisit, jika Anda ingin mengecek cabang jarak jauh yang berbeda dari yang dikonfigurasi untuk cabang saat ini. Ini biasanya berupa remotename / nama cabang . Jika tidak ada parameter yang diberikan, nilai defaultnya adalah @{u}.

Script mengasumsikan bahwa Anda telah melakukan git fetchatau yang git remote updatepertama, untuk membuat cabang pelacakan up to date. Saya tidak membuat ini menjadi skrip karena lebih fleksibel untuk dapat melakukan pengambilan dan perbandingan sebagai operasi terpisah, misalnya jika Anda ingin membandingkan tanpa mengambil karena Anda sudah mengambil baru-baru ini.

Neil Mayhew
sumber
4
@takeshin Saya kira Anda bisa menggabungkan git ls-remote origin -h ref / kepala / master seperti yang disarankan oleh @brool dengan daftar rev git --max-count = 1 origin / master. Jika mereka mengembalikan hash yang sama, cabang jarak jauh belum berubah sejak terakhir kali Anda memperbarui referensi jarak jauh Anda (dengan menarik, mengambil, pembaruan jarak jauh, dll.) Ini akan memiliki keuntungan bahwa Anda tidak perlu menarik konten dari semua melakukan segera, tetapi bisa meninggalkan itu untuk waktu yang lebih nyaman. Namun, karena pembaruan jarak jauh tidak merusak, sebaiknya Anda tetap melakukannya.
Neil Mayhew
2
Anda juga bisa mencoba git status -s -u no, yang memberikan hasil lebih pendek dari git status -u no.
Phillip Cloud
2
@mhulse git remote -v update,. Lihatlah output git remote --helpuntuk penjelasan yang lebih lengkap.
Neil Mayhew
1
@ ChrisMaes Poin yang bagus. Sintaks yang lebih eksplisit diperlukan dengan versi git yang lebih lama. Saya bereksperimen dengan berbagai sistem yang saya miliki dan ternyata @{u}bekerja dengan git 1.8.3.2 tetapi @tidak. Namun @bekerja dengan 1.8.5.4. Moral dari cerita ini: git terus membaik dan layak memiliki versi terbaru yang Anda bisa.
Neil Mayhew
1
Specifier sekarang diperlukan untuk @. Anda dapat menggunakan @ {0} alih-alih @.
Ben Davis
132

Jika Anda memiliki cabang hulu

git fetch <remote>
git status

Jika Anda tidak memiliki cabang hulu

Bandingkan dua cabang:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

Sebagai contoh:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

(Saya berasumsi origin/masteradalah cabang pelacakan jarak jauh Anda)

Jika ada komit yang tercantum dalam output di atas, maka Anda memiliki perubahan yang masuk - Anda harus menggabungkan. Jika tidak ada komitmen terdaftar pada git logsaat itu maka tidak ada yang perlu digabung.

Perhatikan bahwa ini akan berfungsi bahkan jika Anda menggunakan cabang fitur - yang tidak memiliki remote pelacakan, karena jika secara eksplisit merujuk pada origin/masteralih-alih secara implisit menggunakan cabang upstream yang diingat oleh Git.

PlagueHammer
sumber
2
Bahkan notasi yang lebih pendek git fetch; git log HEAD.. --onelinedapat digunakan jika ada cabang jarak jauh default untuk cabang lokal.
phil pirozhkov
@ philpirozhkov Jika Anda memiliki cabang jarak jauh default, "status git" yang sederhana menurut saya. Jawaban saya adalah yang umum untuk dua cabang mana pun, di mana satu mungkin atau tidak dapat melacak yang lain.
PlagueHammer
55
git rev-list HEAD...origin/master --countakan memberi Anda jumlah total komitmen "berbeda" antara keduanya.
Jake Berger
1
pendek dan sederhana. Solusi favorit saya yang baru saja menunjukkan komitmen baru (jempol dua kali)
spankmaster79
Bagaimana saya bisa menggunakan ini dalam file batch (Ubuntu), sehingga saya bisa menjalankan perintah lain hanya dalam kasus perintah ini menunjukkan bahwa diperlukan tarikan?
Ulysses Alves
69

Jika ini untuk skrip, Anda dapat menggunakan:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(Catatan: manfaat dari jawaban ini vs. jawaban sebelumnya adalah Anda tidak perlu perintah terpisah untuk mendapatkan nama cabang saat ini. "HEAD" dan "@ {u}" (hulu cabang saat ini) mengurusnya. Lihat "git rev-parse --help" untuk lebih jelasnya.)

Stephen Haberman
sumber
Saya menemukan @ {u} secara independen dan telah memperbarui jawaban saya sebelum saya melihat jawaban Anda.
Neil Mayhew
1
Akan git rev-parse @{u}benar-benar menunjukkan komit terbaru tanpa git fetch?
Kyle Strand
3
Ini tiketnya! Meskipun, logika Anda menggunakan ==yang berarti "jika tidak ada perubahan dari hulu". Saya dulu !=memeriksa "apakah ada perubahan dari hulu" untuk aplikasi saya. Jangan lupa git fetchdulu!
ChrisPrime
1
Saya menambahkan git fetch, karena memang perlu untuk menjawab pertanyaan aslinya. @kependekan dari HEADbtw.
user1338062
Pengguna Windows akan membutuhkan tanda kutip tunggal sekitar @{u}eggit rev-parse '@{u}'
spuder
36

Perintah

git ls-remote origin -h refs/heads/master

akan mencantumkan head saat ini pada remote - Anda dapat membandingkannya dengan nilai sebelumnya atau melihat apakah Anda memiliki SHA di repo lokal Anda.

brool
sumber
1
Adakah skrip sampel untuk membandingkan nilai-nilai ini?
takeshin
18
git rev-list HEAD...origin/master --countakan memberi Anda jumlah total komitmen "berbeda" antara keduanya.
Jake Berger
3
@ jberger untuk memperjelas, itu hanya akan menunjukkan jumlah komit yang Anda tinggalkan (tidak di depan dan di belakang) dan itu hanya berfungsi jika Anda git fetchatau git remote updatepertama. git statusjuga menunjukkan hitungan, btw.
Dennis
1
@ Dennis saya pikir ..adalah "komit di asal / master, kurangi KEPALA" (yaitu jumlah komit di belakang). Sedangkan, ...adalah perbedaan simetris (yaitu depan dan belakang)
Jake Berger
3
Luar biasa. Sejauh yang saya tahu, ini adalah satu-satunya solusi yang benar-benar memeriksa asal untuk pembaruan tetapi tidak secara implisit melakukan a fetch.
Kyle Strand
35

Berikut adalah Bash satu-kapal yang membandingkan cabang saat ini KEPALA melakukan hash terhadap cabang hulu terpencil, tidak ada yang berat git fetchatau git pull --dry-runoperasi diperlukan:

[ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date

Inilah cara garis yang agak padat ini dipecah:

  • Perintah dikelompokkan dan disarangkan menggunakan sintaks substitusi perintah$(x) Bash .
  • git rev-parse --abbrev-ref @{u}mengembalikan ref hulu yang disingkat (misalnya origin/master), yang kemudian dikonversi ke bidang yang dipisahkan oleh sedperintah piped , mis origin master.
  • String ini dimasukkan ke git ls-remotemana mengembalikan komit kepala dari cabang jauh. Perintah ini akan berkomunikasi dengan repositori jarak jauh. cutPerintah pipa mengekstrak hanya bidang pertama (hash komit), menghapus string referensi tab-terpisah.
  • git rev-parse HEAD mengembalikan hash komit lokal.
  • Sintaks Bash [ a = b ] && x || ymelengkapi one-liner: ini adalah perbandingan string Bash =dalam konstruk tes [ test ], diikuti oleh dan-daftar dan atau-daftar konstruk && true || false.
wjordan
sumber
2
Saya tidak akan menggunakan / g pada sed jika Anda menggunakan garis miring pada nama cabang. Itu hanya "sed / \ // /".
Martyn Davis
@wjordan Solusi Anda gagal saat repositori jarak jauh tidak dapat dijangkau (atau sedang dalam pemeliharaan) dan akan memicu "up to date"
frame
20

Saya sarankan Anda pergi melihat skrip https://github.com/badele/gitcheck . Saya telah mengkodekan skrip ini untuk memeriksa dalam satu pass semua repositori Git Anda, dan ini menunjukkan siapa yang belum berkomitmen dan siapa yang tidak mendorong / menarik.

Di sini hasil sampel:

Masukkan deskripsi gambar di sini

Bruno Adelé
sumber
6
rapi, berpikir untuk menulis ulang di shell murni
Olivier Refalo
1
Sekarang, Anda juga dapat menggunakan gitcheck langsung dari wadah buruh pelabuhan (dengan file Anda di host Anda) Untuk informasi lebih lanjut lihat proyek githeck github
Bruno Adelé
Alat serupa di bash git-multi-repo-tooling . git mrepo -cini akan menampilkan semua komitmen yang tertunda.
Greg
11

Saya mendasarkan solusi ini pada komentar @ jberger.

if git checkout master &&
    git fetch origin master &&
    [ `git rev-list HEAD...origin/master --count` != 0 ] &&
    git merge origin/master
then
    echo 'Updated!'
else
    echo 'Not updated.'
fi
ma11hew28
sumber
Mengacu pada komentar Anda sebelumnya , pada saat ini saya tidak bisa memberikan jawaban yang pasti. Pada saat saya membuat komentar itu, saya menyelam ke kedalaman git dan terutama remote dan diffs. Sudah beberapa bulan sejak itu dan banyak dari pengetahuan itu terkubur di dalam otak saya. ;) Jika Anda mencari jumlah komitmen 'berbeda' di antara keduanya, maka ...tampaknya menjadi bagian yang valid dari solusi Anda.
Jake Berger
1
Terima kasih. Ini bersih.
Shobhit Puri
10

Ada banyak jawaban yang kaya fitur dan cerdik. Untuk memberikan beberapa kontras, saya bisa puas dengan garis yang sangat sederhana.

# Check return value to see if there are incoming updates.
if ! git diff --quiet remotes/origin/HEAD; then
 # pull or whatever you want to do
fi
thuovila
sumber
2
Jawaban asli kurang '!' di if. Nilai pengembalian dari git diff adalah nol, ketika tidak ada perubahan.
thuovila
Solusi terbaik IMO di luar sana, walaupun saya harus mengganti "remote / origin / HEAD" dengan "origin / master" atau revisi lainnya
Matthias Michael Engh
9

Saya pikir cara terbaik untuk melakukan ini adalah:

git diff remotes/origin/HEAD

Dengan anggapan Anda telah mendaftarkan refspec ini. Anda harus jika Anda telah mengkloning repositori, jika tidak (yaitu, jika repo dibuat secara lokal, dan didorong ke remote), Anda perlu menambahkan refspec secara eksplisit.

Jeet
sumber
9

Script di bawah ini berfungsi dengan sempurna.

changed=0
git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1
if [ $changed = 1 ]; then
    git pull
    echo "Updated successfully";
else
    echo "Up-to-date"
fi
Harikrishna
sumber
6

Saya akan melakukan cara yang disarankan oleh brool. Skrip satu baris berikut mengambil SHA1 dari versi yang terakhir Anda komit dan membandingkannya dengan salah satu dari asal yang jauh, dan menarik perubahan hanya jika mereka berbeda. Dan itu bahkan lebih ringan dari solusi berdasarkan git pullatau git fetch.

[ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
-h refs/heads/master |cut -f1` ] && git pull
Claudio Floreani
sumber
Perintah ini gagal, jika repositori git diklon dengan "--depth 1" (untuk membatasi ukuran unduhan). Tahukah Anda, jika ada cara untuk memperbaikinya?
Adam Ryczkowski
Log git ini mengembalikan banyak baris, dan memberikan kesalahan "bash: [: terlalu banyak argumen" Saya akan beralih kegit rev-parse --verify HEAD
Drew Pierce
1
Ini adalah perbandingan string sederhana yang dilakukan oleh bash. Jika ada yang gagal saya sarankan Anda untuk memeriksa sintaks Anda (yaitu Anda salah mengetik). Pertama jalankan git log --pretty=%H ...refs/heads/master^ untuk mendapatkan SHA1 dari versi komit terakhir Anda, dan kemudian jalankan git ls-remote origin -h refs/heads/master |cut -f1 untuk mendapatkan SHA1 dari asal jarak jauh. Keduanya adalah perintah git dan tidak ada hubungannya dengan bash. Apa yang dilakukan bash di dalam tanda kurung siku adalah untuk membandingkan output dari perintah pertama dengan yang kedua, dan jika mereka sama itu mengembalikan true dan berjalan git pull.
Claudio Floreani
"Dan jika mereka sama, ia mengembalikan true dan berjalan git pull". Saya tahu saya menjadi rewel, tetapi hanya untuk menyelamatkan seseorang kebingungan, itu harus "dan jika mereka tidak sama". Juga, untuk alasan apa pun, perintah git pertama tidak bekerja untuk saya. (Saya on git 2.4.1.) Jadi saya hanya menggunakan git log --pretty=%H master | head -n1saja. Tapi saya tidak yakin apakah itu persis sama.
xd1le
6

Jika Anda menjalankan skrip ini, itu akan menguji apakah cabang saat ini membutuhkan git pull:

#!/bin/bash

git fetch -v --dry-run 2>&1 |
    grep -qE "\[up\s+to\s+date\]\s+$(
        git branch 2>/dev/null |
           sed -n '/^\*/s/^\* //p' |
                sed -r 's:(\+|\*|\$):\\\1:g'
    )\s+" || {
        echo >&2 "Current branch need a 'git pull' before commit"
        exit 1
}

Sangat mudah untuk menempatkannya sebagai pre-commit Git hook yang harus dihindari

Merge branch 'foobar' of url:/path/to/git/foobar into foobar

kapan kamu commitsebelumnya pulling.

Untuk menggunakan kode ini sebagai pengait, cukup salin / tempel skrip ke

.git/hooks/pre-commit

dan

chmod +x .git/hooks/pre-commit
Gilles Quenot
sumber
6

Saya hanya ingin memposting ini sebagai posting yang sebenarnya karena mudah untuk melewatkan ini di komentar.

Jawaban yang benar dan terbaik untuk pertanyaan ini diberikan oleh @Jake Berger, Terima kasih banyak, semua orang membutuhkan ini dan semua orang melewatkan ini di komentar. Jadi untuk semua orang yang berjuang dengan ini di sini adalah jawaban yang benar, cukup gunakan output dari perintah ini untuk mengetahui apakah Anda perlu melakukan git pull. jika outputnya 0 maka jelas tidak ada yang diperbarui.

@stackoverflow, beri orang ini lonceng. Terima kasih @ Jake Berger

git rev-list HEAD...origin/master --count will give you the total number of "different" commits between the two.  Jake Berger Feb 5 '13 at 19:23
diegeelvis_SA
sumber
4

Jalankan git fetch (remote)untuk memperbarui referensi jarak jauh Anda, itu akan menunjukkan kepada Anda apa yang baru. Kemudian, ketika Anda checkout cabang lokal Anda, itu akan menunjukkan kepada Anda apakah itu di belakang hulu.

che
sumber
Saya pikir dia sudah memiliki cabang lokal diperiksa, jadi dia perlu sesuatu yang lain untuk menunjukkan apakah itu di belakang dll. Dia dapat melakukan ini dengan status git.
Neil Mayhew
Benar, setelah Anda mengambil remote, git statusakan menunjukkan itu juga.
che
1
Itu adalah sesuatu yang ingin git pull --dry-rundilakukan, tetapi saya pikir ini terlalu berat untuk menjalankan skrip cron setiap menit.
takeshin
@takeshin: Anda tidak dapat memeriksa repositori jarak jauh tanpa melalui jaringan. Jika tidak ada sesuatu yang baru fetchtidak akan melakukan banyak hal selain memeriksa status. Jika Anda memerlukan reaksi yang sangat cepat dan ringan pada pembaruan jarak jauh, Anda mungkin ingin melihat mengaitkan semacam pemberitahuan ke repositori jarak jauh.
che
@takeshin: jika Anda ingin memeriksa repo jarak jauh setiap menit saya pikir Anda telah melewatkan titik DVCS. Seluruh ide adalah untuk dapat berkembang secara mandiri untuk sementara waktu, dan kemudian menyatukan semuanya dengan lancar nanti. Ini tidak seperti cvs, svn, p4 dll. Anda selalu harus mengerjakan apa pun yang terbaru dalam repositori. Jika Anda benar-benar membutuhkan sesuatu yang sedang dikerjakan orang lain, maka Anda harus menggunakan mekanisme komunikasi yang berbeda, seperti email, untuk memberi tahu Anda kapan itu siap untuk ditarik.
Neil Mayhew
4

Semua saran kompleks seperti itu sementara solusinya sangat singkat dan mudah:

#!/bin/bash

BRANCH="<your branch name>"
LAST_UPDATE=`git show --no-notes --format=format:"%H" $BRANCH | head -n 1`
LAST_COMMIT=`git show --no-notes --format=format:"%H" origin/$BRANCH | head -n 1`

git remote update
if [ $LAST_COMMIT != $LAST_UPDATE ]; then
        echo "Updating your branch $BRANCH"
        git pull --no-edit
else
        echo "No updates available"
fi
Manusia Digital
sumber
LAST_COMMIT dan LAST_UPDATE selalu sama bahkan jika ada perubahan
canbax
Solusi ini bagus dan sederhana, perlu git remote updatedieksekusi sebelum kode Anda, untuk mendapatkan info komit asal terbaru
ak93
git remote updateBukankah seharusnya menambahkan sebelum git showperintah?
Setop
2

Inilah versi saya dari skrip Bash yang memeriksa semua repositori di folder yang telah ditentukan:

https://gist.github.com/henryiii/5841984

Itu dapat membedakan antara situasi umum, seperti tarikan yang dibutuhkan dan dorong yang dibutuhkan, dan itu multithreaded, sehingga pengambilan terjadi sekaligus. Ini memiliki beberapa perintah, seperti tarikan dan status.

Letakkan symlink (atau skrip) di folder di jalur Anda, lalu berfungsi sebagai git all status(, dll.). Ini hanya mendukung asal / master, tetapi dapat diedit atau dikombinasikan dengan metode lain.

Henry Schreiner
sumber
1
git ls-remote | cut -f1 | git cat-file --batch-check >&-

akan mendaftar semua yang direferensikan di remote mana pun yang tidak ada di repo Anda. Untuk mengetahui perubahan ref jarak jauh pada hal-hal yang sudah Anda miliki (mis. Me-reset ke commit sebelumnya) membutuhkan sedikit lebih banyak:

git pack-refs --all
mine=`mktemp`
sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
for r in `git remote`; do 
    echo Checking $r ...
    git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
done
jthill
sumber
1

Mungkin ini, jika Anda ingin menambahkan tugas sebagai crontab:

#!/bin/bash
dir="/path/to/root"
lock=/tmp/update.lock
msglog="/var/log/update.log"

log()
{
        echo "$(date) ${1:-missing}" >> $msglog
}

if [ -f $lock ]; then
        log "Already run, exiting..."
else
        > $lock
        git -C ~/$dir remote update &> /dev/null
        checkgit=`git -C ~/$dir status`
        if [[ ! "$checkgit" =~ "Your branch is up-to-date" ]]; then
                log "-------------- Update ---------------"
                git -C ~/$dir pull &>> $msglog
                log "-------------------------------------"
        fi
        rm $lock

fi
exit 0
Altzone
sumber
1

Menggunakan regexp sederhana:

str=$(git status) 
if [[ $str =~ .*Your\ branch\ is\ behind.*by.*commits,\ and\ can\ be\ fast-forwarded ]]; then
    echo `date "+%Y-%m-%d %H:%M:%S"` "Needs pull"
else
    echo "Code is up to date"
fi
Tomas Kukis
sumber
Ini tidak akan berfungsi. status git hanya pemeriksaan lokal, dan itu hanya akan memberi tahu Anda jika cabang Anda ketinggalan jika Anda telah memperbarui def remote Anda.
minhaz1
0

Saya menggunakan versi naskah berdasarkan jawaban Stephen Haberman:

if [ -n "$1" ]; then
    gitbin="git -C $1"
else
    gitbin="git"
fi

# Fetches from all the remotes, although --all can be replaced with origin
$gitbin fetch --all
if [ $($gitbin rev-parse HEAD) != $($gitbin rev-parse @{u}) ]; then
    $gitbin rebase @{u} --preserve-merges
fi

Dengan asumsi skrip ini disebut git-fetch-and-rebase, skrip ini dapat dipanggil dengan argumen opsionaldirectory name dari repositori Git lokal untuk menjalankan operasi. Jika skrip dipanggil tanpa argumen, ia menganggap direktori saat ini menjadi bagian dari repositori Git.

Contoh:

# Operates on /abc/def/my-git-repo-dir
git-fetch-and-rebase /abc/def/my-git-repo-dir

# Operates on the Git repository which the current working directory is part of
git-fetch-and-rebase

Ini tersedia di sini juga.

Tuxdude
sumber
0

Setelah membaca banyak jawaban dan banyak posting, dan menghabiskan setengah hari mencoba berbagai permutasi, inilah yang saya dapatkan.

Jika Anda menggunakan Windows, Anda dapat menjalankan skrip ini di Windows menggunakan Git Bash yang disediakan oleh Git untuk Windows (instalasi atau portable).

Script ini membutuhkan argumen

- jalur lokal misalnya / d / source / project1
- Git URL misalnya https: //[email protected]/username/project1.git
- kata sandi

jika kata sandi tidak boleh dimasukkan pada baris perintah dalam teks biasa,
kemudian modifikasi skrip untuk memeriksa apakah GITPASS kosong; tidak
ganti dan biarkan Git meminta kata sandi

Script akan

- Find the current branch
- Get the SHA1 of the remote on that branch
- Get the SHA1 of the local on that branch
- Compare them.

Jika ada perubahan seperti yang dicetak oleh skrip, maka Anda dapat melanjutkan untuk mengambil atau menarik. Skripnya mungkin tidak efisien, tetapi tugasnya selesai untuk saya.

Pembaruan - 2015-10-30: stderr ke dev null untuk mencegah pencetakan URL dengan kata sandi ke konsol.

#!/bin/bash

# Shell script to check if a Git pull is required.

LOCALPATH=$1
GITURL=$2
GITPASS=$3

cd $LOCALPATH
BRANCH="$(git rev-parse --abbrev-ref HEAD)"

echo
echo git url = $GITURL
echo branch = $BRANCH

# Bash replace - replace @ with :password@ in the GIT URL
GITURL2="${GITURL/@/:$GITPASS@}"
FOO="$(git ls-remote $GITURL2 -h $BRANCH 2> /dev/null)"
if [ "$?" != "0" ]; then
  echo cannot get remote status
  exit 2
fi
FOO_ARRAY=($FOO)
BAR=${FOO_ARRAY[0]}
echo [$BAR]

LOCALBAR="$(git rev-parse HEAD)"
echo [$LOCALBAR]
echo

if [ "$BAR" == "$LOCALBAR" ]; then
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  echo No changes
  exit 0
else
  #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
  #echo pressed $key
  echo There are changes between local and remote repositories.
  exit 1
fi
RuntimeException
sumber
0

Untuk pengguna windows yang akhirnya pada pertanyaan ini mencari ini, saya telah memodifikasi beberapa jawaban menjadi skrip PowerShell. Tweak seperlunya, simpan ke .ps1file dan jalankan sesuai permintaan atau dijadwalkan jika Anda mau.

cd C:\<path to repo>
git remote update                           #update remote
$msg = git remote show origin               #capture status
$update = $msg -like '*local out of date*'
if($update.length -gt 0){                   #if local needs update
    Write-Host ('needs update')
    git pull
    git reset --hard origin/master
    Write-Host ('local updated')
} else {
    Write-Host ('no update needed')
}
Andrew Grothe
sumber
0

Karena jawaban Neils sangat membantu saya di sini adalah terjemahan Python tanpa ketergantungan:

import os
import logging
import subprocess

def check_for_updates(directory:str) -> None:
    """Check git repo state in respect to remote"""
    git_cmd = lambda cmd: subprocess.run(
        ["git"] + cmd,
        cwd=directory,
        stdout=subprocess.PIPE,
        check=True,
        universal_newlines=True).stdout.rstrip("\n")

    origin = git_cmd(["config", "--get", "remote.origin.url"])
    logging.debug("Git repo origin: %r", origin)
    for line in git_cmd(["fetch"]):
        logging.debug(line)
    local_sha = git_cmd(["rev-parse", "@"])
    remote_sha = git_cmd(["rev-parse", "@{u}"])
    base_sha = git_cmd(["merge-base", "@", "@{u}"])
    if local_sha == remote_sha:
        logging.info("Repo is up to date")
    elif local_sha == base_sha:
        logging.info("You need to pull")
    elif remote_sha == base_sha:
        logging.info("You need to push")
    else:
        logging.info("Diverged")

check_for_updates(os.path.dirname(__file__))

hth

frans
sumber
-5

Anda juga dapat menemukan skrip Phing yang melakukannya sekarang.

Saya membutuhkan solusi untuk memperbarui lingkungan produksi saya secara otomatis dan kami sangat senang berkat skrip yang saya bagikan ini.

Script ditulis dalam XML dan membutuhkan Phing .

Pol Dellaiera
sumber
Mungkin itu bukan ide yang baik untuk menyalin rekatkan skrip di sini, saya masih memperbarui ...
Pol Dellaiera