Pytanie Jak ustalić, czy dany skrót hasha istnieje w danej gałęzi?


Tło: Korzystam z zautomatyzowanego systemu kompilacji, który przyjmuje jako argument wejściowy skrót git, a także nazwę oddziału, w którym znajduje się ten skrót, i tworzy go. Jednak system budujący używa samego skrótu, aby sprawdzić kod i zbudować go - po prostu przechowuje nazwę gałęzi, jak podano, w metadanych DB kompilacji.

Martwię się, że programiści przypadkowo podadzą niewłaściwą nazwę oddziału po uruchomieniu kompilacji, powodując zamieszanie, gdy ludzie przeglądają historię kompilacji.

Więc jak mogę potwierdzić, przed przekazaniem nazwy skrótu i ​​nazwy gałęzi do systemu kompilacji, że dany skrót pochodzi z danej gałęzi?


35
2018-03-14 22:39


pochodzenie


dlaczego potrzebujesz nazwy oddziału? wydaje się dodatkową, nieprzydatną informacją dla systemu kompilacji. I tak naprawdę nie widzę, w jaki sposób byłoby to przydatne dla logów budujących czytanie programisty. - hasen
Potrzebowałbyś nazwy oddziału, na wypadek gdyby twój workflow miał, nie wiem, rozwinięty i główny oddział używany do wdrożenia i chciałbyś wiedzieć, czy zatwierdzenia dostały się do jakiegoś konkretnego? Przy okazji, proszę przyjąć prawdziwą odpowiedź. - Spencer Williams
@Pinko Myślę, że wybrana odpowiedź powinna być ten. Ponieważ ma o wiele więcej głosów i jest znacznie prostsza dzięki użyciu natywnej funkcjonalności git. - Omar Al-Ithawi


Odpowiedzi:


Hmm, to użycie nazwy oddziału wydaje się podejrzane. Podobnie jak w odpowiedzi Dustina, może istnieć wiele gałęzi zawierających zatwierdzenie. Dlaczego jedna z tych nazw jest lepsza od innej w tym celu?


Jeśli interesuje Cię tylko jedna konkretna gałąź, możesz obliczyć "podstawę scalenia" między gałęzią a zatwierdzeniem.

W poniższych diagramach zatwierdzenie do zbudowania jest Ckońcówka żądanej gałęzi jest T, a podstawa połączenia jest oznaczona etykietą M ponad tym.

  • Gdyby M równa się C równa się T, to zobowiązanie do zbudowania jest wierzchołkiem żądanej gałęzi.

                   M
                   ↓
    o--o--o--o--o--x  branch  # x is both C and T
    
  • Gdyby M równa się C, a końcówka żądanej gałęzi jest pochodną zobowiązania do zbudowania.

          M
          ↓
    o--o--C--o--o--T  branch
    
  • Gdyby M równa się T, to zobowiązanie do zbudowania jest potomkiem końcówki żądanej gałęzi.

          M
          ↓
    o--o--T           branch
           \
            o--o--C
    
  • Gdyby M równa się więc coś innego C jest potomkiem jakiegoś przodka T.

          M
          ↓
    o--o--o--o--o--T  branch
           \
            o--o--C
    
  • Jeżeli nie ma M, zatwierdzenie do zbudowania nie jest powiązane z żądaną gałęzią.

    o--o--o--o--o--T branch
    
    o--o--o--o--C
    

Możesz zrobić to w ten sposób:

#!/bin/sh

# Usage: is-ancestor-of <branch> <commit>

if test $# -ne 2; then
    echo "$0"': invalid arguments'
    exit 128
fi
claimed_branch="$1"
commit="$2"

merge_base="$(git merge-base "$commit" "$claimed_branch")" &&
  test -n "$merge_base" &&
  test "$merge_base" = "$(git rev-parse --verify "$commit")" &&
  exit 0

echo "$commit is not an ancestor of $claimed_branch" 1>&2
exit 1

Powyższy skrypt w rzeczywistości nie wymaga ani nie sprawdza, czy argument "branch" jest gałęzią (może to być dowolne commit-ish). Aby sprawdzić, czy coś rzeczywiście jest gałęzią, możesz użyć czegoś takiego:

#!/bin/sh

# Usage: is-branch <branch>

if test $# -ne 1; then
    echo "$0"': invalid arguments'
    exit 128
fi
branch="$1"

# check various branch hierarchies, adjust as needed
git show-ref --verify refs/heads/"$branch" ||
git show-ref --verify refs/remotes/"$branch" || {
    echo "not a branch name: $branch" 1>&2
    exit 1
}

Więc możesz użyć ich razem, aby sprawdzić, czy coś jest gałęzią i że pewne zatwierdzenie jest w tej gałęzi:

is-branch "$claimed_branch" && is-ancestor-of "$claimed_branch" "$commit_to_build"

9
2018-03-15 05:38



Bardzo interesujące. +1 - VonC
Prostsze rozwiązanie @ stackoverflow.com/a/2444924/292408 - Elijah Lynn
Dlaczego do cholery zrobiłbyś to, gdy git ma wbudowane lepsze rozwiązanie? Dlaczego, na Boga, ta śmiesznie pokrętna odpowiedź została zaakceptowana, gdy nie jest najwyraźniej najlepsza? Zmarnowałem czas przesiewając to, zamiast przewijać do odpowiedzi, która powinna znajdować się na górze. Łał... - Spencer Williams
Czy administratorzy SO mogą zmienić zaakceptowaną odpowiedź? Jeśli tak, to powinno być zrobione w tym przypadku. - Michael Leonard
@SpencerWilliams Zawsze dawaj ludziom korzyści z wątpliwości. Odpowiedź najprawdopodobniej została przyjęta, ponieważ --contains opcja do git branch został dodany tylko w git v1.5.4 (wrzesień 2010 r.), podczas gdy ta odpowiedź została podana w marcu 2010 r., czyli w tym czasie był najlepsza odpowiedź. - Adam Spiers


Możesz zapytać git branch bezpośrednio, które gałęzie zawierają dane zatwierdzenie:

% git branch -a --contains 4f08c85ad
* master
  remotes/origin/bug_872
  remotes/origin/bug_898
  remotes/origin/master

117
2018-03-15 03:27



Usunąć -a możliwość wystawienia listy tylko z lokalnego oddziału - ismailsunni
Zamiast tego można użyć konkretnej gałęzi -a na przykład $ git branch develop --contains 4f08c85ad - Omar Al-Ithawi


Jeden możliwy brak rozwiązania byłoby przeanalizować wynik:

$ git reflog show myBranch

i zobacz czy twój hasz jest w tym.

C:\Prog\Git\tests\rep\main>git reflog show patches
786a190 patches@{0}: rebase finished: refs/heads/patches onto 74630b983db476c323b1d3f6771e57484551240e
8448d0f patches@{1}: master~1: updating HEAD
74630b9 patches@{2}: commit: test2
1e73e36 patches@{3}: branch: Created from master

Utrzymuję to jako wspólnotową odpowiedź na Wiki, aby pamiętać Igor Zevaka i Chris Johnsenkomentarze:

Czy to działa po klonie?
  Jestem pewien, że twój reflog zaczyna się po sklonowaniu pilota. Więc jeśli oddział miał zatwierdzenie przed klonem, nie wyświetliłby się w reflogie.

Występują również problemy z popychaniem, rozgałęzianiem, pobieraniami (dla gałęzi "zdalnego śledzenia") i ciągnięciami (typu scalania lub rebase), w których tylko nowe zatwierdzenie końcówki kończy się reflogiem.
  Również reflogi są domyślnie wyłączone w repozytoriach nagich (najczęstsze miejsce docelowe naciśnięć).
  Ponadto, jeśli "oszustwo" jest problemem, jest to tylko kwestia edytowania pliku tekstowego w celu dodania lub usunięcia wpisów do rejestru, ale jest to trudniejsza próba zmiany samego wykresu historii.


1



Czy to działa po klonie? Jestem pewien, że twój reflog zaczyna się po sklonowaniu pilota. Więc jeśli oddział miał zatwierdzenie przed klonem, nie wyświetliłby się w reflogie. - Igor Zevaka
Racja, @Igor Zevaka. Występują również problemy z popychaniem i rebazami (gdzie tylko nowe zatwierdzenie końcówki kończy się reflogiem). Również reflogi są domyślnie wyłączone w repozytoriach nagich (najczęstsze miejsce docelowe naciśnięć). Ponadto, jeśli "oszustwo" jest problemem, jest to tylko kwestia edytowania pliku tekstowego w celu dodania lub usunięcia wpisów do rejestru, ale jest to trudniejsza próba zmiany samego wykresu historii. - Chris Johnsen