Bagaimana menemukan orang tua terdekat dari cabang Git?

419

Katakanlah saya memiliki repositori lokal berikut dengan pohon komit seperti ini:

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

masteradalah saya ini terbaru kode rilis stabil , developadalah saya ini adalah 'berikutnya' kode rilis , dan featuremerupakan fitur baru yang disiapkan untukdevelop .

Apa yang saya ingin dapat lakukan pada repo jarak jauh saya menggunakan kait, adalah untuk mendorong untuk featureditolak kecuali komit fadalah keturunan langsung developKEPALA. yaitu pohon komit terlihat seperti ini karena fitur telah git rebaseaktif d.

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

Jadi apakah mungkin untuk:

  • Identifikasi cabang induk dari feature?
  • Identifikasi komit di cabang induk yang fmerupakan turunan dari?

Dari sana saya akan memeriksa apa KEPALA cabang induk, dan melihat apakah fpendahulu cocok dengan cabang orangtua KEPALA, untuk menentukan apakah fitur perlu diubah kembali.

Peter Farmer
sumber
pertanyaan ini harus diulang untuk menemukan induk dari induk.
Tim Boland

Jawaban:

348

Dengan asumsi bahwa repositori jarak jauh memiliki salinan cabang pengembangan (deskripsi awal Anda menjelaskannya dalam repositori lokal, tetapi kedengarannya seperti itu juga ada di remote), Anda harus dapat mencapai apa yang saya pikir Anda inginkan, tetapi pendekatannya sedikit berbeda dari apa yang Anda bayangkan.

Sejarah Git didasarkan pada DAG komitmen. Cabang (dan "ref" secara umum) hanyalah label sementara yang menunjukkan komitmen spesifik dalam DAG commit yang terus berkembang. Dengan demikian, hubungan antar cabang dapat bervariasi dari waktu ke waktu, tetapi hubungan antara komitmen tidak.

    ---o---1                foo
            \
             2---3---o      bar
                  \
                   4
                    \
                     5---6  baz

Sepertinya bazdidasarkan pada (versi lama) bar? Tetapi bagaimana jika kita menghapus bar?

    ---o---1                foo
            \
             2---3
                  \
                   4
                    \
                     5---6  baz

Sekarang sepertinya bazdidasarkan pada foo. Tetapi nenek moyang baztidak berubah, kami hanya menghapus label (dan hasilnya menjuntai komit). Dan bagaimana jika kita menambahkan label baru di 4?

    ---o---1                foo
            \
             2---3
                  \
                   4        quux
                    \
                     5---6  baz

Sekarang sepertinya bazdidasarkan pada quux. Meski begitu, nenek moyang tidak berubah, hanya label yang berubah.

Namun, jika kita bertanya "apakah melakukan 6turunan dari komitmen 3?" (dengan asumsi 3dan nama 6lengkap SHA-1 komit), maka jawabannya adalah "ya", apakah label bardan quuxada atau tidak.

Jadi, Anda dapat mengajukan pertanyaan seperti "apakah komit yang didorong adalah turunan dari ujung cabang pengembangan saat ini ?", Tetapi Anda tidak dapat dengan andal bertanya "apa cabang induk dari komit yang didorong?".

Sebagian besar pertanyaan yang andal yang tampaknya mendekati apa yang Anda inginkan adalah:

Untuk semua leluhur komit terdorong (tidak termasuk ujung kembang saat ini dan leluhurnya), yang memiliki kembang ujung saat ini sebagai induk:

  • apakah setidaknya ada satu komit seperti itu ada?
  • apakah semua komitmen seperti itu dilakukan oleh orang tua tunggal?

Yang dapat diimplementasikan sebagai:

pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_children_of_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
    ,)     echo "must descend from tip of '$basename'"
           exit 1 ;;
    ,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
           exit 1 ;;
    ,*)    exit 0 ;;
esac

Ini akan mencakup sebagian dari apa yang Anda inginkan dibatasi, tetapi mungkin tidak semuanya.

Untuk referensi, berikut adalah sejarah contoh yang diperluas:

    A                                   master
     \
      \                    o-----J
       \                  /       \
        \                | o---K---L
         \               |/
          C--------------D              develop
           \             |\
            F---G---H    | F'--G'--H'
                    |    |\
                    |    | o---o---o---N
                     \   \      \       \
                      \   \      o---o---P
                       \   \   
                        R---S

Kode di atas dapat digunakan untuk menolak Hdan Ssaat menerima H', J, K, atau N, tetapi akan juga menerima Ldan P(mereka melibatkan gabungan, tetapi mereka tidak menggabungkan ujung berkembang ).

Untuk juga menolak Ldan P, Anda dapat mengubah pertanyaan dan bertanya

Untuk semua leluhur komit yang terdorong (tidak termasuk tip perkembangan saat ini dan leluhurnya):

  • apakah ada komitmen dengan dua orang tua?
  • jika tidak, apakah setidaknya satu komit tersebut memiliki tip mengembangkan (hanya) induknya?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_commits_beyond_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
    *\ *)          echo "must not push merge commits (rebase instead)"
                   exit 1 ;;
    *"$baserev"*)  exit 0 ;;
    *)             echo "must descend from tip of '$basename'"
                   exit 1 ;;
esac
Chris Johnsen
sumber
Saya mendapatkan ini: git: fatal: argumen ambigu '...': baik revisi dan nama file. apa maksud tiga titik?
Jack Ukleja
1
@Schneider Saya cukup yakin '...' dimaksudkan untuk menjadi penampung dalam contoh ini: jika Anda menggantinya dengan SHA dari komit yang Anda coba lakukan pemeriksaan ini terhadap (katakanlah, KEPALA cabang) Anda sedang aktif), semuanya berfungsi dengan baik.
Daniel Brady
Terima kasih atas jawaban terperinci ini! Ini sangat berguna. Saya ingin membuat pengait yang serupa, tetapi saya tidak ingin meng-hard-code nama cabang pengembangan. Berarti saya ingin kait untuk mencegah rebase ke cabang selain dari cabang induk. Jika saya memahami jawaban Anda dengan baik (saya baru mengenal bash and stuff) ini tidak tercakup dalam jawaban Anda, bukan? Apakah ada cara untuk melakukan ini?
Kemeia
Apakah Anda bersedia menjawab pertanyaan terkait? Saya tidak bisa membuat kode Anda bekerja di repositori REMOTE. Berikut ini tautan ke pertanyaan tindak lanjut tentang bagaimana menyesuaikan pendekatan Anda agar berfungsi dengan repositori REMOTE: stackoverflow.com/questions/49619492/…
CodeMed
Ini tidak bekerja untuk saya ketika saya punya develop > release > feature, saya akan mendapatkan kembali dan itu membutuhkan mengetahui orang tua. Solusi untuk masalah saya adalah stackoverflow.com/a/56673640/2366390
verdverm
241

Sebuah rephrasal

Cara lain untuk mengutarakan pertanyaannya adalah "Apa komit terdekat yang berada di cabang selain cabang saat ini, dan cabang mana yang itu?"

Sebuah solusi

Anda dapat menemukannya dengan sedikit sihir baris perintah

git show-branch \
| sed "s/].*//" \
| grep "\*" \
| grep -v "$(git rev-parse --abbrev-ref HEAD)" \
| head -n1 \
| sed "s/^.*\[//" 

Dengan awk :

git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \
| awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'

Begini cara kerjanya:

  1. Menampilkan riwayat tekstual semua komit, termasuk cabang jarak jauh.
  2. Leluhur dari komit saat ini ditunjukkan oleh bintang. Saring semua yang lainnya.
  3. Abaikan semua komitmen di cabang saat ini.
  4. Hasil pertama adalah cabang leluhur terdekat. Abaikan hasil lainnya.
  5. Nama cabang ditampilkan [dalam kurung]. Abaikan segala sesuatu di luar tanda kurung, dan tanda kurung.
  6. Terkadang nama cabang akan menyertakan ~ # atau ^ # untuk menunjukkan berapa banyak komit antara komit yang direferensikan dan tip cabang. Kami tidak peduli. Abaikan mereka.

Dan Hasilnya

Menjalankan kode di atas

 A---B---D <-master
      \
       \
        C---E---I <-develop
             \
              \
               F---G---H <-topic

Akan memberi Anda developjika Anda menjalankannya dari H dan masterjika Anda menjalankannya dari I.

Kode tersedia sebagai intisari

Joe Chrysler
sumber
24
Menghapus backtick belakang yang menyebabkan kesalahan. Ketika menjalankan perintah ini, saya mendapatkan sejumlah besar peringatan, mengeluh tentang setiap cabang yang mengatakancannot handle more than 25 refs
Jon L.
1
@ JoChrysler apakah Anda pikir Anda dapat membuatnya satu baris, bukan 2, dan mungkin membuatnya bekerja di Mac karena acktidak tersedia di Mac (seseorang menyarankan untuk mengganti ackdengan grep)
nonopolarity
53
Maaf, itu salah. Inilah yang benar yang bekerja untuk saya:git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
droidbot
15
@droidbot Bagus, tetapi perlu perpipaan pemesanan ulang untuk menghindari penghapusan referensi ketika grep -v menangkap pesan commit atau nama cabang Anda adalah bagian dari nama cabang lain. git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
gaal
3
@OlegAbrazhaev Saya tidak tahu apakah Anda pernah menjawab pertanyaan Anda. menggunakan alias git dari: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"berfungsi untuk saya
mduttondev
111

Anda juga dapat mencoba:

git log --graph --decorate
rcde0
sumber
5
git log --graph --decorate --simplify-by-decorationdimana --graphopsional.
Na13-c
1
git log --graph --decorate --simplify-by-decoration --oneline
anishtain4
106

orangtua git

Anda bisa menjalankan perintah

git parent

untuk menemukan induk cabang, jika Anda menambahkan jawaban @ Jo Chrysler sebagai alias git . Ini akan menyederhanakan penggunaan.

Buka file gitconfig yang terletak di "~/.gitconfig"menggunakan editor teks apa pun. (Untuk linux). Dan untuk Windows jalur ".gitconfig" umumnya terletak dic:\users\your-user\.gitconfig

vim  ~/.gitconfig

Tambahkan perintah alias berikut dalam file:

[alias]
            parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"

Simpan dan keluar dari editor.

Jalankan perintah git parent

Itu dia!

NIKHIL CM
sumber
5
Ini solusi hebat. Akan sangat membantu untuk juga menambahkan beberapa sampel output untuk memastikan hasil yang diharapkan. Ketika saya menjalankannya, saya mendapat beberapa peringatan sebelum baris terakhir yang saya yakini adalah nama cabang induknya.
ttemple
4
Bekerja seperti pesona! Untuk pengguna windows, .gitconfig umumnya terletak di c: \ users \ your-user \ .gitconfig
zion
12
Dapatkan cannot handle more than 25 refspengecualian.
shajin
dapatkah seseorang mengedit ini untuk menangani peringatan? @ Mencoba, bisakah Anda?
NIKHIL CM
@NIKHILCM bekerja seperti seorang Juara. Tapi saya punya pertanyaan di sini apakah orang tua menunjukkan dari mana cabang dibuat atau yang lain?
Hariprasath
52

Saya punya solusi untuk masalah Anda secara keseluruhan (tentukan jika featurediturunkan dari ujung develop), tetapi tidak berfungsi menggunakan metode yang Anda uraikan.

Anda dapat menggunakan git branch --containsdaftar semua cabang turun dari ujung develop, kemudian gunakan grepuntuk memastikan featureada di antara mereka.

git branch --contains develop | grep "^ *feature$"

Jika ada di antara mereka, itu akan dicetak " feature" ke output standar dan memiliki kode pengembalian 0. Jika tidak, tidak akan mencetak apa pun dan memiliki kode pengembalian 1.

Daniel Stutzbach
sumber
1
Ini berfungsi tetapi perlu dicatat bahwa ini bisa memakan waktu lama di repositori yang memiliki banyak referensi. Itu membuatnya sedikit kurang ideal untuk berjalan di, misalnya, kait pra-terima.
ebneter
Saya sedang mencari cabang, kami akan menyebutnya <branch>, di mana saya tampil: git checkout -b <branch-2>dari ... INI adalah jawabannya! Tidak perlu grep, kok. git branch --contains <branch>
Poopy McFartnoise
44

Ini bekerja dengan baik untuk saya.

git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Jawaban sopan dari: @droidbot dan @Jistanidiot

Murali Mopuru
sumber
Ya, tapi kadang-kadang itu membuat Anda "pipa rusak" dari grep.
Vladislav Rastrusny
1
*bukan regex yang tepat untuk diteruskan ke grep. Harus digunakan grep -F '*'atau grep '\*'sebagai gantinya. Sebaliknya solusi yang bagus.
arielf
Saya tidak mendapat hasil.
Sandip Subedi
bekerja untuk saya ....
roottraveller
11

Karena tidak ada jawaban di atas yang berfungsi pada repositori kami, saya ingin berbagi dengan cara saya sendiri, menggunakan gabungan terbaru di git log:

#!/bin/bash
git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 10

Masukkan ke dalam skrip bernama git-last-merges, yang juga menerima nama cabang sebagai argumen (bukan cabang saat ini) serta yang laingit log argumen

Dari output, kita dapat secara manual mendeteksi cabang induk berdasarkan esensi cabang sendiri dan jumlah penggabungan dari masing-masing cabang.

EDIT: Jika Anda sering menggunakan git rebasecabang anak (dan penggabungan sering diteruskan sehingga tidak ada terlalu banyak gabungan yang dilakukan), jawaban ini tidak akan berfungsi dengan baik, jadi saya menulis skrip untuk menghitung komit di depan (normal dan gabungan) , dan di belakang komit (seharusnya tidak ada penggabungan di belakang di cabang induk) pada semua cabang dibandingkan dengan cabang saat ini. Jalankan saja skrip ini dan beri tahu saya apakah ini cocok untuk Anda atau tidak

#!/bin/bash
HEAD="`git rev-parse --abbrev-ref HEAD`"
echo "Comparing to $HEAD"
printf "%12s  %12s   %10s     %s\n" "Behind" "BehindMerge" "Ahead" "Branch"
git branch | grep -v '^*' | sed 's/^\* //g' | while read branch ; do
    ahead_merge_count=`git log --oneline --merges $branch ^$HEAD | wc -l`
    if [[ $ahead_merge_count != 0 ]] ; then
        continue
    fi
    ahead_count=`git log --oneline --no-merges $branch ^$HEAD | wc -l`
    behind_count=`git log --oneline --no-merges ^$branch $HEAD | wc -l`
    behind_merge_count=`git log --oneline --merges ^$branch $HEAD | wc -l`
    behind="-$behind_count"
    behind_merge="-M$behind_merge_count"
    ahead="+$ahead_count"
    printf "%12s  %12s   %10s     %s\n" "$behind" "$behind_merge" "$ahead" "$branch"
done | sort -n
saeedgnu
sumber
Terima kasih. Meskipun ini mungkin tidak berfungsi dengan baik jika Anda rebasesering menggunakan (dan penggabungan fast-forwardsering dilakukan). Saya akan mengedit jawaban saya jika saya menemukan solusi yang lebih baik.
saeedgnu
1
Satu-satunya? jawab sejauh ini yang masuk akal bagi saya dalam kasus di mana cabang saat ini adalah master. Sebagian besar solusi lain memberikan hasil acak (dan jelas salah) dalam kasus tepi yang diakui ini di mana tidak ada cabang induk yang sebenarnya.
arielf
Ini satu-satunya jawaban yang berhasil untuk saya. Untuk mendapatkan orang tua pertama alih-alih daftar 10 pertama, Anda dapat menggunakan ini: git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
lots0logs
10

Sebuah solusi

Solusi berdasarkangit show-branch tidak cukup bekerja untuk saya (lihat di bawah), jadi saya telah menggabungkannya dengan yang didasarkan padagit log dan berakhir dengan ini:

git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
      | grep -v "(HEAD" \                               # removes current head (and branch)
      | head -n1 \                                      # selects only the closest decoration
      | sed 's/.* (\(.*\)) .*/\1/' \                    # filters out everything but decorations
      | sed 's/\(.*\), .*/\1/' \                        # picks only the first decoration
      | sed 's/origin\///'                              # strips "origin/" from the decoration

Keterbatasan dan Peringatan

  • KEPALA dapat dilepas (banyak alat CI melakukannya untuk memastikan mereka membangun komit yang benar di cabang tertentu), tetapi cabang asal dan cabang lokal harus sama atau "di atas" KEPALA saat ini.
  • Tidak boleh ada tag di jalan (saya kira; saya belum menguji skrip saat melakukan dengan tag antara cabang child dan parent)
  • skrip mengandalkan fakta "KEPALA" selalu terdaftar sebagai dekorasi pertama oleh logperintah
  • menjalankan script pada masterdandevelop hasil (kebanyakan) di<SHA> Initial commit

Hasil

 A---B---D---E---F <-origin/master, master
      \      \
       \      \
        \      G---H---I <- origin/hotfix, hotfix
         \
          \
           J---K---L <-origin/develop, develop
                \
                 \
                  M---N---O <-origin/feature/a, feature/a
                       \   \
                        \   \
                         \   P---Q---R <-origin/feature/b, feature/b
                          \
                           \
                            S---T---U <-origin/feature/c, feature/c

Meskipun keberadaan cabang lokal (mis. Hanya origin/topicada sejak komit Odiperiksa langsung oleh SHA-nya), skrip harus dicetak sebagai berikut:

  • Untuk komit G, H,I (cabang hotfix) →master
  • Untuk komit M, N,O (cabang feature/a) →develop
  • Untuk komit S, T,U (cabang feature/c) →develop
  • Untuk komit P, Q,R (cabang feature/b) →feature/a
  • Untuk komit J, K, L(cabang develop) → <sha> Initial commit*
  • Untuk komit B, D, E, F(cabang master) →<sha> Initial commit

* - atau masterjika developkomitmen berada di atas KEPALA master (~ master akan maju cepat untuk berkembang)


Mengapa tidak menunjukkan cabang bekerja untuk saya

Solusi berdasarkangit show-branch terbukti tidak dapat diandalkan untuk saya dalam situasi berikut:

  • HEAD terlepas - termasuk kasing kepala terpisah berarti mengganti grep '\*' \untuk `grep '! \ - dan itu hanyalah awal dari semua masalah
  • menjalankan script pada masterdandevelop hasil dalam developdan `` masing-masing
  • cabang padamaster cabang ( hotfix/cabang) berakhir dengan developsebagai induk karena masterinduk cabang terdekat mereka ditandai dengan !alih - alih *karena suatu alasan.
Matt Stuvysant
sumber
2
Hanya jawaban yang berhasil - sebagai git alias:"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
Ian Kemp
8

Ingat bahwa, seperti yang dijelaskan dalam "Git: Menemukan darimana asal sebuah komit berasal" , Anda tidak dapat dengan mudah menentukan cabang tempat komit tersebut dibuat (cabang dapat diubah namanya, dipindahkan, dihapus ...), meskipun itu git branch --contains <commit>adalah permulaan.

  • Anda dapat kembali dari komit ke komit hingga git branch --contains <commit>tidak mencantumkan featurecabang dan daftar developcabang,
  • bandingkan komit SHA1 ke /refs/heads/develop

Jika kedua melakukan id cocok, Anda baik untuk pergi (itu berarti featurecabang memiliki asal di KEPALA develop).

VONC
sumber
6

Sihir baris perintah JoeChrysler dapat disederhanakan. Inilah logika Joe - untuk singkatnya saya telah memperkenalkan parameter bernama cur_branchpengganti substitusi perintah `git rev-parse --abbrev-ref HEAD`ke dalam kedua versi; yang dapat diinisialisasi seperti:

cur_branch=$(git rev-parse --abbrev-ref HEAD)

Lalu, inilah pipa Joe:

git show-branch -a           |
  grep '\*'                  | # we want only lines that contain an asterisk
  grep -v "$cur_branch"      | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed

Kita dapat mencapai hal yang sama seperti kelima perintah individu itu menyaring dalam perintah yang relatif sederhana awk:

git show-branch -a |
  awk -F'[]^~[]' '/\*/ && !/'"$cur_branch"'/ {print $2;exit}'  

Itu rusak seperti ini:

-F'[]^~[]' 

membagi garis menjadi bidang di ], ^, ~, dan [karakter.

/\*/                      

Temukan garis yang mengandung tanda bintang

&& !/'"$cur_branch"'/

... tetapi bukan nama cabang saat ini

{ print $2;               

Ketika Anda menemukan garis seperti itu, cetak bidang keduanya (yaitu, bagian antara kemunculan pertama dan kedua dari karakter pemisah bidang kami). Untuk nama-nama cabang yang sederhana, itu adalah apa yang ada di antara kurung; untuk referensi dengan lompatan relatif, itu hanya nama tanpa pengubah. Jadi, set pemisah bidang kami menangani maksud kedua sedperintah.

  exit }

Kemudian segera keluar. Ini berarti hanya memproses baris pencocokan pertama, jadi kami tidak perlu menyalurkan output head -n 1.

Mark Reed
sumber
3
Perhatikan bahwa beberapa cabang bisa hilang dari output karena terlalu banyak referensi. Mereka ditampilkan sebagai peringatan pada stderr sebagai gantinya.
Zitrax
5

Berikut ini adalah implementasi PowerShell dari solusi Mark Reed:

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }
chrisevett
sumber
5

Saya tidak mengatakan ini adalah cara yang baik untuk menyelesaikan masalah ini, namun ini sepertinya bekerja untuk saya.

git branch --contains $(cat .git/ORIG_HEAD) Masalahnya adalah bahwa menjalankan file sedang mengintip ke dalam git, jadi ini belum tentu kompatibel ke depan (atau kompatibel ke belakang).

pengguna1529413
sumber
3

Implementasi lintas platform dengan Ant

    <exec executable="git" outputproperty="currentBranch">
        <arg value="rev-parse" />  
        <arg value="--abbrev-ref" />  
        <arg value="HEAD" />  
    </exec>

    <exec executable="git" outputproperty="showBranchOutput">
        <arg value="show-branch" />  
        <arg value="-a" />  
    </exec>

    <loadresource property="baseBranch">
      <propertyresource name="showBranchOutput"/>
          <filterchain>
            <linecontains>
              <contains value="*"/>
            </linecontains>
            <linecontains negate="true">
              <contains value="${currentBranch}"/>
            </linecontains>
            <headfilter lines="1"/>
            <tokenfilter>
                <replaceregex pattern=".*\[(.*)\].*" replace="\1"/>
                <replaceregex pattern="[\^~].*" replace=""/>
            </tokenfilter>
          </filterchain>
    </loadresource>

    <echo message="${currentBranch} ${baseBranch}" />
Enargit
sumber
2

@Mark Reed: Anda harus menambahkan bahwa garis komit seharusnya tidak hanya mengandung tanda bintang, tetapi mulai dengan tanda bintang! Kalau tidak, komit pesan yang mengandung tanda bintang juga termasuk dalam baris yang cocok. Jadi seharusnya:

git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'

atau versi panjang:

git show-branch -a           |
  awk '^\*'                  | # we want only lines that contain an asterisk
  awk -v "$current_branch"   | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed`
Ladiko
sumber
2
vbc=$(git rev-parse --abbrev-ref HEAD)
vbc_col=$(( $(git show-branch | grep '^[^\[]*\*' | head -1 | cut -d* -f1 | wc -c) - 1 )) 
swimming_lane_start_row=$(( $(git show-branch | grep -n "^[\-]*$" | cut -d: -f1) + 1 )) 
git show-branch | tail -n +$swimming_lane_start_row | grep -v "^[^\[]*\[$vbc" | grep "^.\{$vbc_col\}[^ ]" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Mencapai tujuan yang sama dengan jawaban Mark Reed, tetapi menggunakan pendekatan yang jauh lebih aman yang tidak nakal dalam sejumlah skenario:

  1. Komit terakhir cabang induk adalah penggabungan, membuat kolom ditampilkan - tidak*
  2. Pesan komit berisi nama cabang
  3. Pesan komit berisi *
Haoyang Feng
sumber
0

Siapa pun yang ingin melakukan ini akhir-akhir ini - aplikasi SourceTree dari Atlassian menunjukkan kepada Anda representasi visual yang hebat tentang bagaimana cabang Anda berhubungan satu sama lain, yaitu Di mana mereka memulai dan di mana mereka saat ini duduk dalam urutan komit (mis. HEAD atau 4 komit di belakang, dll.) .

jake
sumber
0

Jika Anda menggunakan Source Tree lihat detail komit Anda> Parents> maka Anda akan melihat angka komit digarisbawahi (tautan)

Mike6679
sumber
0

Sebuah alternatif: git rev-list master | grep "$(git rev-list HEAD)" | head -1

Dapatkan komit terakhir yang merupakan cabang saya dan master(atau cabang apa pun yang ingin Anda tentukan)

Alexander Woods
sumber
0

Ini tidak bekerja untuk saya ketika saya telah melakukan sesuatu seperti develop > release-v1.0.0 > feature-foo, itu akan berjalan jauh ke belakang untuk berkembang, perhatikan ada rebase yang terlibat, tidak yakin apakah itu memperparah masalah saya ...

Berikut ini memang memberikan hash komit yang benar untuk saya

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
verdverm
sumber