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ę
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).
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-)
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
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 '* '.
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;
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
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.)
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 )
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