Laat alle lokale vestigingen zien zonder afstandsbediening

Probleem: ik wil een manier om alle lokale vestigingen die ik heb die geen afstandsbediening hebben, te verwijderen. Het is gemakkelijk genoeg om de namen van de branches in een git branch -D {branch_name}te pipen, maar hoe krijg ik die lijst in de eerste plaats?

Bijvoorbeeld:

Ik maak een nieuwe branch aan zonder remote:

$ git co -b no_upstream

Ik vermeld al mijn vestigingen, en er is er maar één met een afstandsbediening

$ git branch -a
master
* no_upstream
remotes/origin/HEAD -> origin/master
remotes/origin/master

Welke opdracht kan ik uitvoeren om no_upstreamals antwoord te krijgen?

Ik kan git rev-parse --abbrev-ref --symbolic-full-name @{u}uitvoeren en dat laat zien dat het geen afstandsbediening heeft:

$ git rev-parse --abbrev-ref --symbolic-full-name @{u}
error: No upstream configured for branch 'no_upstream'
error: No upstream configured for branch 'no_upstream'
fatal: ambiguous argument '@{u}': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Maar aangezien dit een fout is, kan ik het niet gebruiken of doorsturen naar andere commando’s. Ik ben van plan dit te gebruiken als ofwel een shellscript alias’d naar git-delete-unbranchedof misschien een supereenvoudige Gem te maken zoals git-branch-delete-orphans


Antwoord 1, autoriteit 100%

Ik raad aan om git branch --formatte gebruiken om de exacte uitvoer te specificeren die je wilt van het git branchcommando. Door dat te doen, kun je alleen de refname en de upstream eruit halen, zoals dit:

git branch --format "%(refname:short) %(upstream)"

Het voert de vertakkingen uit samen met de vertakkingen op afstand als ze bestaan, in het volgende formaat:

25-timeout-error-with-many-targets
31-target-suggestions refs/remotes/origin/31-target-suggestions
54-feedback-link refs/remotes/origin/54-feedback-link
65-digest-double-publish

Zodra je deze mooi opgemaakte uitvoer hebt, is het net zo eenvoudig om hem door awkte sturen om je lijst te krijgen:

git branch --format "%(refname:short) %(upstream)" | awk '{if (!$2) print $1;}'

Resulteert in de volgende uitvoer:

25-timeout-error-with-many-targets
65-digest-double-publish

Het gedeelte awkdrukt de eerste kolom af als er geen tweede kolom is.

Bonus: maak een alias

Maak het gemakkelijk om een ​​alias te maken in je globale .gitconfig-bestand (of waar dan ook):

[alias]
  local-branches = "!git branch --format '%(refname:short) %(upstream:short)' | awk '{if (!$2) print $1;}'"

Bonus: filteren op afstand

Als je om de een of andere reden meerdere tracking remotes hebt voor verschillende branches, is het eenvoudig genoeg om aan te geven met welke remote je wilt controleren. Voeg gewoon de externe naam toe aan het awk-patroon. In mijn geval is het origin, dus ik kan dit doen:

git branch --format "%(refname:short) %(upstream)" | awk '$2 !~/\/origin\// { print $1 }'

Belangrijk: de backslash moet in de alias worden geëscaped, anders heb je een ongeldig gitconfig-bestand.


Vorige antwoord

Het vorige antwoord was functioneel vergelijkbaar, maar gebruikte het volgende als uitgangspunt. Na verloop van tijd hebben commentatoren erop gewezen dat een regex onbetrouwbaar is vanwege de mogelijke variantie in een commit-bericht, dus ik raad deze methode niet langer aan. Maar hier is het ter referentie:

Ik ontdekte onlangs git branch -vvwat de “zeer uitgebreide” versie is van het git branchcommando.

Het voert de vertakkingen uit samen met de vertakkingen op afstand als ze bestaan, in het volgende formaat:

 25-timeout-error-with-many-targets    206a5fa WIP: batch insert
  31-target-suggestions                 f5bdce6 [origin/31-target-suggestions] Create target suggestion for team and list on save
* 54-feedback-link                      b98e97c [origin/54-feedback-link] WIP: Feedback link in mail
  65-digest-double-publish              2de4150 WIP: publishing-state

Zodra je deze mooi opgemaakte uitvoer hebt, is het net zo eenvoudig om hem door cuten awkte sturen om je lijst te krijgen:

git branch -vv | cut -c 3- | awk '$3 !~/\[/ { print $1 }'

Antwoord 2, autoriteit 29%

git branch(zonder opties) lijsten alleen lokale vestigingen, maar u weet niet of ze een externe vestiging volgen of niet.

Normaal gesproken moeten die lokale branches worden verwijderd zodra ze zijn samengevoegd met master(zoals te zien in deze uitgave van git-sweep):

git branch --no-contains master --merged master | xargs git branch -d

Dit is niet zo compleet als je wilt, maar het is een begin.

Met --merged, worden alleen branches weergegeven die zijn samengevoegd in de genoemde commit (d.w.z. de branches waarvan de tip-commits bereikbaar zijn vanaf de genoemde commit).


Antwoord 3, autoriteit 18%

Ik heb een soortgelijk probleem. Ik wil alle lokale vertakkingen verwijderen die verre vertakkingen volgden die nu zijn verwijderd. Ik vind dat git remote prune originonvoldoende was om de branches te verwijderen die ik weg wil. Zodra de afstandsbediening is verwijderd, wil ik dat de lokale ook verdwijnt. Dit is wat voor mij werkte:

Van mijn ~/.gitconfig:

[alias]
  prune-branches = !git remote prune origin && git branch -vv | grep ': gone]' | awk '{print $1}' | xargs -r git branch -d

Hier is een git config --global ...commando om dit eenvoudig toe te voegen als git prune-branches:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | xargs -r git branch -d'

OPMERKING: ik heb de -dgewijzigd in -din mijn huidige configuratie, omdat ik Git niet wil horen klagen over niet-verbonden takken. U misschienwilt u deze functionaliteit ook. Zo ja, gebruik dan gewoon -din plaats van -daan het einde van die opdracht.

Bovendien, FWIW, zou je globale configuratiebestand bijna altijd ~/.gitconfigzijn.

(OS X-correctie)

Zoals geschreven werkt dit niet op OS X vanwege het gebruik van xargs -r(bedankt, Korny).

De -ris om te voorkomen dat xargsgit branch -duitvoert zonder een branchnaam, wat resulteert in een foutmelding ” fatal: branch name required“. Als je de foutmelding niet erg vindt, kun je eenvoudig het argument -rverwijderen naar xargsen je bent helemaal klaar.

Als je echter geen foutmelding wilt zien (en echt, wie kan jou de schuld geven), dan heb je iets anders nodig dat controleert op een lege pijp. Als je misschien ifnevan moreutils. Je zou ifnevóór xargsinvoegen, waardoor xargsniet meer met lege gegevens kan worden uitgevoerd. OPMERKING: ifnebeschouwt allesals niet leeg, dit geldt ook voor lege regels, dus het kan zijn dat je die foutmelding nog steeds ziet. Ik heb dit niet getest op OS X.

Hier is die git configregel met ifne:

git config --global alias.prune-branches '!git remote prune origin && git branch -vv | grep '"'"': gone]'"'"' | awk '"'"'{print $1}'"'"' | ifne xargs git branch -d'

Antwoord 4, autoriteit 15%

Laat bewerkt:

Beter is

git for-each-ref  --format='%(refname:short) %(upstream)'  refs/heads \
| awk '$2 !~/^refs\/remotes/'

Over GNU/anything

for b in `git branch|sed s,..,,`; do
    git config --get branch.$b.remote|sed Q1 && echo git branch -D $b
done

Indien meer dan een handvol takken waarschijnlijk waren, zouden er betere manieren zijn, met behulp van comm -23op de uitvoer van git branch|sed|sorten git config -l|sed|sort.


5, Autoriteit 13%

Dit werkt voor mij:

git branch -vv | grep -v origin

(Als uw afstandsbediening iets anders dan herkomst wordt genoemd, vervangt u dat).

Hiermee wordt alle takken weergegeven die geen afstandsbediening volgen, wat klinkt als wat u zoekt.


6

Hier is iets dat ik in PowerShell heb gebruikt met opmerkingen om uit te leggen wat het doet. In een poging om het duidelijk te maken wat er aan de hand is, heb ik geen verkorte PowerShell-opdrachten (aliassen) gebruikt. Voel je vrij om het te comprimeren op het gewenste niveau van crypticess 🙂

$verboseList = @(git branch -vv)
foreach ($line in $verboseList)
{
    # Get the branch name
    $branch = [regex]::Match($line, "\s(\S+)\s").Captures.Groups[1].Value
    # Check if the line contains text to indicate if the remote is deleted
    $remoteGone = $line.Contains(": gone]")
    # Check if the line does not contain text to indicate it is a tracking branch (i.e., it's local)
    $isLocal = !($line.Contains("[origin/"))
    if ($remoteGone -or $isLocal)
    {
        # Print the branch name
        $branch
    }
}

7

Het meest gestemd antwoord hier werkt niet op mijn systeem Zie gist

Dit volgende werkt en is redelijk schoon.

git branch -v | awk '$3 == "[gone]" { print $1 }' | xargs git branch -D

Gebruik -D als u niet-samengevoegde vestigingen wilt verwijderen.


8

Een paar van de bestaande antwoorden combineren:

[alias]
        branch-local = !git branch -vv | cut -c 3- | egrep '([0-9a-f]{7} [^[])|(: gone\\])' | sed -E 's/(^.+[0-9a-f]{7} (\\[.+\\])?).*$/\\1/'

b.v.:

$ git branch-local
autogen_autoreconf      fcfb1c6 [github/autogen_autoreconf: gone]
autotools_documentation 72dc477 [github/autotools_documentation: gone]
cray-mpich-messy        2196f4b
epel-sphinx             cfda770
lammps                  07d96a7 [github/lammps: gone]
lark-error              9ab5d6c [github/lark-error: gone]
no-root2                c3894d1
openmpi-cray            69326cf [github/openmpi-cray: gone]
shellcheck-cleanup      40d90ec
travis-python36         cde072e
update_vagrant_default  4f69f47 [github/update_vagrant_default: gone]
web-docs                e73b4a8

9

Geen van de bestaande antwoorden lijkt voor mij te werken.

Hier is mijn oplossing om lokale filialen te vermelden die niet ook op afstand zijn

comm -13 <(git branch -r | sed 's/origin\/\(.*\)/\1/g' | cut -c 3-) <(git branch | cut -c 3-)

en hier is een uitleg over hoe het werkt:

  1. Overweeg de lijst met alle externe takken (zonder ‘oorsprong /’ of toonaangevende ruimtes)
    git branch -r | sed 's/origin\/\(.*\)/\1/g' | cut -c 3-

  2. Overweeg de lijst met alle lokale takken (zonder asterisken of toonaangevende ruimtes)
    git branch | cut -c 3-

  3. Vergelijk deze twee lijsten en laat me alles zien in de lijst 2 (mijn lokale takken) die niet in lijst 1 (de lijst met externe filialen)
    comm -13 <(git branch -r | sed 's/origin\/\(.*\)/\1/g' | cut -c 3-) <(git branch | cut -c 3-)

Comm kan een combinatie van de vlaggen -1, -2 en -3-aangegeven
Welk bestand om lijnen te onderdrukken van (uniek voor bestand 1, uniek voor bestand 2
of gewoon voor beide)

Other episodes