Jak przechodzić przez wszystkie gałęzie Gita używając skryptu bash

Jak mogę przeglądać wszystkie lokalne gałęzie w repozytorium używając skryptu bash. Muszę iterować i sprawdzić, czy jest jakaś różnica między gałęzią a niektórymi odległymi gałęziami. Ex

for branch in $(git branch); 
do
    git log --oneline $branch ^remotes/origin/master;
done

Muszę zrobić coś takiego jak wyżej, ale problem, z którym się borykam, to $(Git branch) daje mi foldery wewnątrz folderu repozytorium wraz z gałęziami obecnymi w repozytorium.

Czy w ten sposób można rozwiązać ten problem? A może jest inny sposób to?

Dziękuję

Author: Arun P Johny, 2010-10-02

8 answers

Nie powinieneś używać Git branch podczas pisania skryptów. Git dostarcza interfejs "plumbing" , który jest jawnie zaprojektowany do użycia w skryptach (wiele aktualnych i historycznych implementacji zwykłych komend Gita (add, checkout, merge, itp.) używać tego samego interfejsu).

Polecenie instalacyjne, które chcesz to git for-each-ref :

git for-each-ref --shell \
  --format='git log --oneline %(refname) ^origin/master' \
  refs/heads/

Uwaga: nie potrzebujesz prefiksu remotes/ na zdalnym ref, chyba że masz inne refy, które powodują origin/master dopasuj wiele miejsc w ścieżce wyszukiwania nazwy ref (patrz " symboliczna nazwa ref. ... "w sekcji określającej zmiany w git-rev-parse(1)). Jeśli próbujesz jednoznacznie uniknąć dwuznaczności, wybierz pełną nazwę ref: refs/remotes/origin/master.

Otrzymasz wynik w następujący sposób:

git log --oneline 'refs/heads/master' ^origin/master
git log --oneline 'refs/heads/other' ^origin/master
git log --oneline 'refs/heads/pu' ^origin/master

Możesz przekierować to wyjście do sh .

Jeśli nie podoba Ci się pomysł generowania kodu powłoki, możesz zrezygnować z odrobiny solidności* i zrobić to:

for branch in $(git for-each-ref --format='%(refname)' refs/heads/); do
    git log --oneline "$branch" ^origin/master
done

* Nazwy Ref powinny być bezpieczne przed podziałem słów powłoki (zobacz Git-check-ref-format(1)). Osobiście trzymałbym się poprzedniej wersji (wygenerowany kod powłoki); Jestem bardziej przekonany, że nic niewłaściwego nie może się z nią zdarzyć.

Ponieważ podałeś bash i obsługuje tablice, możesz zachować bezpieczeństwo i nadal unikać generowania wnętrzności pętli:

branches=()
eval "$(git for-each-ref --shell --format='branches+=(%(refname))' refs/heads/)"
for branch in "${branches[@]}"; do
    # …
done

Możesz zrobić coś podobnego z $@ jeśli nie używasz powłoki obsługującej tablice ({[8] } do inicjalizacji i set -- "$@" %(refname) do dodawania elementów).

 129
Author: Chris Johnsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-10 19:12:38

Dzieje się tak dlatego, żegit branch oznacza bieżącą gałąź gwiazdką, np.:

$ git branch
* master
  mybranch
$ 

Więc $(git branch) rozszerza się do np. * master mybranch, a następnie * rozszerza się do listy plików w bieżącym katalogu.

Nie widzę oczywistej opcji, aby nie drukować gwiazdki, ale można ją odciąć:

$(git branch | cut -c 3-)
 42
Author: Matthew Slattery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-02 15:49:47

Proponuję $(git branch|grep -o "[0-9A-Za-z]\+") jeśli lokalne oddziały są nazwane cyframi, a-z i/lub tylko literami a-z

 4
Author: Xin Guo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-20 03:43:00

Przyjęta odpowiedź jest poprawna i naprawdę powinna być stosowana, ale rozwiązanie problemu w bash jest świetnym ćwiczeniem w zrozumieniu, jak działają powłoki. Sztuczka, aby to zrobić przy użyciu bash bez wykonywania dodatkowej manipulacji tekstem, jest zapewnienie, że wyjście Git branch nigdy nie zostanie rozszerzone jako część polecenia wykonywanego przez powłokę. Zapobiega to rozszerzaniu się gwiazdki w rozszerzeniu nazwy pliku (krok 8) rozszerzenia powłoki (zobacz http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html )

Użyj bash while construct z poleceniem read, aby rozciąć wyjście gałęzi git na linie. "*"Będzie odczytywane jako literalny znak. Użyj instrukcji case, aby ją dopasować, zwracając szczególną uwagę na dopasowane wzorce.

git branch | while read line ; do                                                                                                        
    case $line in
        \*\ *) branch=${line#\*\ } ;;  # match the current branch
        *) branch=$line ;;             # match all the other branches
    esac
    git log --oneline $branch ^remotes/origin/master
done

Gwiazdki zarówno w konstrukcji bash , jak i w podstawieniu parametru muszą być unikane z odwrotnymi ukośnikami, aby zapobiec interpretacji powłoki one jako znaki pasujące do wzorca. Spacje są również unikane (aby zapobiec tokenizacji), ponieważ dosłownie pasujesz do '* '.

 4
Author: BitByteDog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-30 08:39:58

I iteracji jak to na przykład:

for BRANCH in `git branch --list|sed 's/\*//g'`;
  do 
    git checkout $BRANCH
    git fetch
    git branch --set-upstream-to=origin/$BRANCH $BRANCH
  done
git checkout master;
 4
Author: Djory Krache,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-21 11:40:51

Najprostsza opcja do zapamiętania moim zdaniem:

git branch | grep "[^* ]+" -Eo

Wyjście:

bamboo
develop
master

Opcja-o grepa (--only-matching) ogranicza wyjście tylko do pasujących części wejścia.

Ponieważ ani spacja, ani * nie są ważne w nazwach gałęzi Git, zwraca listę gałęzi bez dodatkowych znaków.

Edit: jeśli jesteś w ' odłączona Głowa ' , musisz odfiltrować bieżący wpis:

git branch --list | grep -v "HEAD detached" | grep "[^* ]+" -oE

 2
Author: staafl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-01 14:00:11

Co zrobiłem, zastosowałem się do twojego pytania (&zainspirowany ccpizza wspominając tr):

git branch | tr -d ' *' | while IFS='' read -r line; do git log --oneline "$line" ^remotes/origin/master; done

(często używam pętli while. Podczas gdy dla konkretnych rzeczy na pewno chciałbyś użyć wskazanej nazwy zmiennej ["branch", na przykład], przez większość czasu zajmuję się tylko robieniem czegoś z każdą linią wejścia. Użycie 'line' zamiast 'branch' jest ukłonem w stronę wielokrotnego użytku / pamięci mięśniowej / wydajności.)

 2
Author: Jan Kyu Peblik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-30 18:36:39

Rozszerzenie od @finn ' s answer (thank you!), poniższe pozwala na iterację nad gałęziami bez tworzenia interweniującego skryptu powłoki. Jest wystarczająco wytrzymały, o ile nie ma nowych linii w nazwie gałęzi:)

git for-each-ref --format='%(refname)' refs/heads  | while read x ; do echo === $x === ; done

Pętla while działa w subshell, co zwykle jest w porządku, chyba że ustawiasz Zmienne powłoki, do których chcesz uzyskać dostęp w bieżącej powłoce. W takim przypadku używasz substytucji procesu, aby odwrócić rurę:

while read x ; do echo === $x === ; done < <( git for-each-ref --format='%(refname)' refs/heads )
 1
Author: Chris Cogdon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-23 22:31:09