Załóżmy, że mam następujące lokalne repozytorium z drzewem zatwierdzeń, takim jak to:
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
jest mój, to jest najnowszy stabilny kod wydania , develop
jest mój, to jest „następny” kod wydania i feature
jest to nowa funkcja w przygotowaniudevelop
.
To, co chcę robić na moim zdalnym repozytorium za pomocą haków, polega na feature
odmowie wypchnięcia, chyba że zatwierdzenie f
jest bezpośrednim potomkiem develop
HEAD. tzn. drzewo zatwierdzeń wygląda tak, ponieważ funkcja jest git rebase
włączona d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
Czy możliwe jest:
- Zidentyfikować nadrzędną gałąź
feature
? - Zidentyfikuj zatwierdzenie w gałęzi nadrzędnej, która
f
jest potomkiem?
Stamtąd sprawdziłbym, czym jest HEAD gałęzi nadrzędnej, i sprawdzić, czy f
poprzednik pasuje do HEAD gałęzi nadrzędnej, aby ustalić, czy funkcja wymaga ponownego bazowania.
Odpowiedzi:
Zakładając, że zdalne repozytorium posiada kopię rozwinięcia gałęzi (początkowy opis opisuje go w lokalnym repozytorium, ale to brzmi jak również istnieje w pilocie), powinieneś być w stanie osiągnąć to, co myślę, że chcesz, ale podejście różni się nieco od tego, co sobie wyobrażałeś.
Historia Git opiera się na DAG zatwierdzeń. Gałęzie (i ogólnie „referencje”) są tylko przejściowymi etykietami, które wskazują na określone zatwierdzenia w stale rosnącym DAG zatwierdzania. W związku z tym relacje między oddziałami mogą się zmieniać w czasie, ale związek między zatwierdzeniami się nie zmienia.
Wygląda na to, że
baz
jest oparty na (starej wersji)bar
? Ale co jeśli usuniemybar
?Teraz wygląda na to, że
baz
jest oparty nafoo
. Ale pochodzeniebaz
się nie zmieniło, po prostu usunęliśmy etykietę (i wynikające z tego zwisające zatwierdzenie). A jeśli dodamy nową etykietę w4
?Teraz wygląda na to, że
baz
jest oparty naquux
. Mimo to pochodzenie się nie zmieniło, zmieniły się tylko etykiety.Gdybyśmy jednak pytali „czy popełnienie
6
potomka popełnienia3
?” (zakładając3
i6
są to pełne nazwy zatwierdzeń SHA-1), wówczas odpowiedź brzmiałaby „tak”, niezależnie od tego, czy etykietybar
iquux
są obecne, czy nie.Można więc zadawać pytania typu „czy wypychany zatwierdzenie jest potomkiem aktualnej końcówki gałęzi rozwijania ?”, Ale nie można rzetelnie zadać pytania „jaka jest gałąź nadrzędna zatwierdzonego przekazu?”.
Najbardziej wiarygodne pytanie, które wydaje się zbliżać do tego, czego chcesz, to:
Które można zaimplementować jako:
To obejmie część tego, co chcesz ograniczyć, ale może nie wszystko.
Dla odniesienia, oto rozszerzona przykładowa historia:
Powyższy kod można wykorzystać do odrzucenia
H
iS
przyjmującH'
,J
,K
, lubN
, ale również zaakceptowaćL
iP
(obejmują one scala, ale nie połączyć końcówkę rozwijać ).Aby odrzucić
L
iP
, możesz zmienić pytanie i zadaćźródło
develop > release > feature
, wróciłem do rozwoju i wymaga to znajomości z rodzicem. Rozwiązaniem mojego problemu było stackoverflow.com/a/56673640/2366390Reefrasal
Innym sposobem sformułowania pytania jest „Jaki jest najbliższy zatwierdzenie rezydujące w gałęzi innej niż bieżąca gałąź i która to gałąź?”
Rozwiązanie
Możesz go znaleźć z odrobiną magii wiersza poleceń
Z awk :
Oto jak to działa:
I wynik
Uruchomienie powyższego kodu
Daje ci,
develop
jeśli uruchomisz go z H, amaster
jeśli uruchomisz go z I.Kod jest dostępny jako istota
źródło
cannot handle more than 25 refs
ack
nie jest dostępny na Macu (ktoś sugerował zastąpienieack
gogrep
)git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"
działa dla mnieMożesz także spróbować:
źródło
git log --graph --decorate --simplify-by-decoration
gdzie--graph
jest opcjonalne.git log --graph --decorate --simplify-by-decoration --oneline
git rodzic
Możesz po prostu uruchomić polecenie
git parent
aby znaleźć rodzica oddziału, jeśli dodasz odpowiedź @Joe Chrysler jako alias git . Uprości to użytkowanie.
Otwórz plik gitconfig zlokalizowany przy
"~/.gitconfig"
użyciu dowolnego edytora tekstu. (Dla systemu Linux). W przypadku systemu Windows ścieżka „.gitconfig” zazwyczaj znajduje się pod adresemc:\users\your-user\.gitconfig
Dodaj następujące polecenie aliasu w pliku:
Zapisz i zamknij edytor.
Uruchom polecenie
git parent
Otóż to!
źródło
cannot handle more than 25 refs
wyjątku.Mam rozwiązanie twojego ogólnego problemu (określ, czy
feature
pochodzi on od końcówkidevelop
), ale nie działa przy użyciu opisanej przez ciebie metody.Możesz użyć,
git branch --contains
aby wyświetlić listę wszystkich gałęzi pochodzących od końcadevelop
, a następnie użyć,grep
aby upewnić się, żefeature
jest wśród nich.Jeśli jest wśród nich, drukuje
" feature"
na standardowe wyjście i ma kod powrotu 0. W przeciwnym razie nic nie wydrukuje i będzie miał kod powrotu 1.źródło
<branch>
tam, gdzie występowałem:git checkout -b <branch-2>
od ... To jest odpowiedź! Naprawdę nie potrzeba grepa.git branch --contains <branch>
Dla mnie to działa dobrze.
Dzięki uprzejmości odpowiedzi od: @droidbot i @Jistanidiot
źródło
*
nie jest właściwym wyrażeniem regularnym do przekazania do grep. Powinien użyćgrep -F '*'
lubgrep '\*'
zamiast. W przeciwnym razie dobre rozwiązanie.Ponieważ żadna z powyższych odpowiedzi nie działała w naszym repozytorium, chcę udostępnić swój własny sposób, korzystając z najnowszych połączeń
git log
:Umieść go w skrypcie o nazwie
git-last-merges
, który akceptuje również nazwę gałęzi jako argument (zamiast bieżącej gałęzi), a także innegit log
argumentyNa podstawie danych wyjściowych możemy ręcznie wykryć gałąź nadrzędną na podstawie własnych konwencji rozgałęziania i liczby połączeń z każdej gałęzi.
EDYCJA: Jeśli
git rebase
często korzystasz z gałęzi potomnych (a połączenia są często przewijane do przodu, więc nie ma zbyt wielu zatwierdzeń scalania), ta odpowiedź nie zadziała dobrze, więc napisałem skrypt, aby liczyć przyszłe zatwierdzenia (normalne i scalanie) i za zatwierdzeniami (nie powinno być żadnego scalania za w łączu nadrzędnym) we wszystkich gałęziach w porównaniu z bieżącym. Po prostu uruchom ten skrypt i daj mi znać, czy działa dla Ciebie, czy nieźródło
rebase
często używasz (a scalania sąfast-forward
często edytowane). Zmienię swoją odpowiedź, jeśli znajdę lepsze rozwiązanie.git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
Rozwiązanie
Rozwiązanie oparte na
git show-branch
mnie nie do końca działało (patrz poniżej), więc połączyłem je z rozwiązaniem opartym na tymgit log
i skończyłem z tym:Ograniczenia i zastrzeżenia
log
komendęmaster
idevelop
wyniki (w większości) w<SHA> Initial commit
Wyniki
Pomimo istnienia lokalnego oddziału (np.
origin/topic
Jest obecny tylko, ponieważ zatwierdzenieO
zostało wyewidencjonowane bezpośrednio przez jego SHA), skrypt powinien wydrukować w następujący sposób:G
,H
,I
(oddziałhotfix
) →master
M
,N
,O
(oddziałfeature/a
) →develop
S
,T
,U
(oddziałfeature/c
) →develop
P
,Q
,R
(oddziałfeature/b
) →feature/a
J
,K
,L
(oddziałdevelop
) →<sha> Initial commit
*B
,D
,E
,F
(oddziałmaster
) →<sha> Initial commit
* - lub
master
jeślidevelop
zatwierdzenia byłyby na GŁOWICY mistrza (~ rozwinięcie byłoby szybkie, aby rozwinąć master)Dlaczego nie pokazałem gałęzi pracy dla mnie
Rozwiązanie oparte na
git show-branch
mnie okazało się niewiarygodne w następujących sytuacjach:grep '\*' \
„grep”! \ - i to dopiero początek wszystkich kłopotówmaster
idevelop
powodujedevelop
i odpowiednio `master
gałęzi (hotfix/
gałęziach) kończą siędevelop
jako nadrzędne, ponieważ ich najbliższymaster
nadrzędny oddział został oznaczony!
zamiast z*
jakiegoś powodu.źródło
"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
Pamiętaj, że zgodnie z opisem w „Git: Znajdowanie gałęzi, z której pochodzi zatwierdzenie” , nie możesz łatwo wskazać gałęzi, w której dokonano tego zatwierdzenia (gałęzie można zmienić, przenieść, usunąć ...), nawet jeśli
git branch --contains <commit>
jest to początek.git branch --contains <commit>
nie wyświetli się listafeature
gałęzi i listadevelop
gałęzi,/refs/heads/develop
Jeśli dwa zatwierdzenia id zgadzają się, możesz iść (to znaczy, że
feature
gałąź ma swój początek w HEADdevelop
).źródło
Magię wiersza poleceń JoeChryslera można uprościć. Oto logika Joe - dla zwięzłości wprowadziłem parametr o nazwie
cur_branch
zamiast podstawiania poleceń`git rev-parse --abbrev-ref HEAD`
w obu wersjach; które można zainicjować w następujący sposób:Oto potok Joe:
Możemy osiągnąć to samo, co wszystkie pięć z tych pojedynczych filtrów poleceń w stosunkowo prostym
awk
poleceniu:To się psuje:
podzielić linię na pola w
]
,^
,~
oraz[
znaków.Znajdź linie zawierające gwiazdkę
... ale nie bieżąca nazwa oddziału
Kiedy znajdziesz taką linię, wydrukuj jej drugie pole (czyli część między pierwszym a drugim wystąpieniem naszych znaków separatora pól). W przypadku prostych nazw gałęzi będzie to tylko to, co znajduje się w nawiasach; dla referencji z względnymi skokami będzie to tylko nazwa bez modyfikatora. Nasz zestaw separatorów pól obsługuje zamiar obu
sed
poleceń.Następnie wyjdź natychmiast. Oznacza to, że zawsze przetwarza tylko pierwszą pasującą linię, więc nie musimy przepuszczać danych wyjściowych
head -n 1
.źródło
Oto implementacja PowerShell rozwiązania Marka Reeda:
źródło
Nie twierdzę, że to dobry sposób na rozwiązanie tego problemu, jednak wydaje się, że to działa na mnie.
git branch --contains $(cat .git/ORIG_HEAD)
Problem polega na tym, że cat'owanie pliku zagląda do wewnętrznego działania git, więc niekoniecznie jest on zgodny z poprzednimi wersjami (lub poprzedni).źródło
Wdrożenie wieloplatformowe z Ant
źródło
@ Mark Reed: Powinieneś dodać, że linia zatwierdzenia powinna nie tylko zawierać gwiazdkę, ale zaczynać od gwiazdki! W przeciwnym razie komunikaty zgodności zawierające gwiazdkę są również uwzględniane w dopasowanych wierszach. Tak powinno być:
git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'
lub długa wersja:
źródło
Osiąga te same cele, co odpowiedź Marka Reeda, ale stosuje znacznie bezpieczniejsze podejście, które nie zachowuje się źle w wielu scenariuszach:
-
nie*
*
źródło
Każdy, kto chce to zrobić w dzisiejszych czasach - aplikacja SourceTree firmy Atlassian pokazuje doskonałą wizualną relację między swoimi oddziałami, tj. Gdzie się zaczęły i gdzie obecnie znajdują się w kolejności zatwierdzania (np. HEAD lub 4 zobowiązania za nimi itp.) .
źródło
Jeśli użyjesz drzewa źródeł, spójrz na szczegóły zatwierdzenia> Rodzice> zobaczysz podkreślone numery zatwierdzeń (linki)
źródło
Alternatywa:
git rev-list master | grep "$(git rev-list HEAD)" | head -1
Uzyskaj ostatni zatwierdzenie, że jest to jednocześnie moja gałąź i
master
(lub dowolna gałąź, którą chcesz określić)źródło
Nie działało to dla mnie, kiedy zrobiłem coś takiego
develop > release-v1.0.0 > feature-foo
, cofnęłoby się aż do rozwoju, zauważ, że był to rebase, nie jestem pewien, czy to komplikuje mój problem ...Poniższe dane dały mi poprawny hash zatwierdzenia
źródło