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_upstream
als 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-unbranched
of misschien een supereenvoudige Gem te maken zoals git-branch-delete-orphans
Antwoord 1, autoriteit 100%
Ik raad aan om git branch --format
te gebruiken om de exacte uitvoer te specificeren die je wilt van het git branch
commando. 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 awk
te 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 awk
drukt 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 -vv
wat de “zeer uitgebreide” versie is van het git branch
commando.
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 cut
en awk
te 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 origin
onvoldoende 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 -d
gewijzigd in -d
in 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 -d
in plaats van -d
aan het einde van die opdracht.
Bovendien, FWIW, zou je globale configuratiebestand bijna altijd ~/.gitconfig
zijn.
(OS X-correctie)
Zoals geschreven werkt dit niet op OS X vanwege het gebruik van xargs -r
(bedankt, Korny).
De -r
is om te voorkomen dat xargs
git branch -d
uitvoert zonder een branchnaam, wat resulteert in een foutmelding ” fatal: branch name required
“. Als je de foutmelding niet erg vindt, kun je eenvoudig het argument -r
verwijderen naar xargs
en 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 ifne
vóór xargs
invoegen, waardoor xargs
niet meer met lege gegevens kan worden uitgevoerd. OPMERKING: ifne
beschouwt 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 config
regel 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 -23
op de uitvoer van git branch|sed|sort
en 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:
-
Overweeg de lijst met alle externe takken (zonder ‘oorsprong /’ of toonaangevende ruimtes)
git branch -r | sed 's/origin\/\(.*\)/\1/g' | cut -c 3-
-
Overweeg de lijst met alle lokale takken (zonder asterisken of toonaangevende ruimtes)
git branch | cut -c 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)