[HN Gopher] I found a useful Git one liner buried in leaked CIA ...
___________________________________________________________________
I found a useful Git one liner buried in leaked CIA developer docs
Author : spencerldixon
Score : 565 points
Date : 2026-02-20 14:03 UTC (8 hours ago)
(HTM) web link (spencer.wtf)
(TXT) w3m dump (spencer.wtf)
| whazor wrote:
| I currently have a TUI addiction. Each time I want something to
| be easier, I open claude-code and ask for a TUI. Now I have a git
| worktree manager where I can add/rebase/delete. As TUI library I
| use Textual which claude handles quite well, especially as it can
| test-run quite some Python code.
| lionkor wrote:
| That sounds like a complete waste of time and tokens to me,
| what is the benefit? So each time you do something, you let
| Claude one shot a tui? This seems like a waste of compute and
| your time
| MarsIronPI wrote:
| On the contrary. Once these tools exist they exist forever,
| independently of Claude or a Claude Code subscription. IMO
| this is the best way to use AI for personal use.
| duneisagoodbook wrote:
| yeah! they should focus on more productive pursuits, like
| telling people online what to do with their time and
| resources.
| morissette wrote:
| And these are things outside of our control.
| htnthrow11220 wrote:
| They said each time they want something to be easier, not
| each time they do something. And they didn't mention it has
| to be one-shot. You might have read too quickly and you've
| responded to something that didn't actually exist.
| bmacho wrote:
| Now that I think about it, if Claude can put most useful
| functions in a TUI and make them discoverable (show them in a
| list), than this could be better than asking for one-liners
| (and forgetting them) every single time.
|
| Maybe I'll try using small TUI too.
| Trufa wrote:
| The amount of little tools I'm creating for myself is
| incredible, 4.6 seems like it can properly one/two shot it now
| without my attention.
|
| Did you open source that one? I was thinking of this exact same
| thing but wanted to think a little about how to share deps,
| i.e. if I do quick worktree to try a branch I don't wanna npm i
| that takes forever.
|
| Also, if you share it with me, there's obviously no
| expectations, even it's a half backed vibecoded mess.
| elliotbnvl wrote:
| The deps question is huge, let me know if you solve it.
| CalebJohn wrote:
| If I'm understanding the problem correctly, this should be
| solved by pnpm [1]. It stores packages in a global cache,
| and hardlinks to the local node_packages. So running
| install in a new worktree should be instant.
|
| [1]: https://pnpm.io/motivation
| SauntSolaire wrote:
| What's the point of open sourcing something you one shot with
| an LLM? At that point just open source the prompt you used to
| generate it.
| freedomben wrote:
| Testing. If you share something you've tested and know
| works, that's way better than sharing a prompt which will
| generate untested code which then has to be tested. On top
| of that it seems wasteful to burn inference compute (and $)
| repeating the same thing when the previous output would be
| superior anyway.
|
| That said, I do think it would be awesome if including
| prompts/history in the repos somehow became a thing. Not
| only would it help people learn and improve, but it would
| allow tweaking.
| NetOpWibby wrote:
| To save time and energy?
| unshavedyak wrote:
| I've been wanting similar but have instead been focused on
| GUI. My #1 issue with TUI is that I've never liked code jumps
| very smooth high fps fast scrolling. Between that and
| terminal lacking variable font sizes, I'd vastly prefer TUIs,
| but I just struggle to get over those two issues.
|
| I've been entirely terminal based for 20 years now and those
| issues have just worn me down. Yet I still love terminal for
| its simplicity. Rock and a hard place I guess.
| whazor wrote:
| This is how I solve the dependencies with Nix: https://gist.g
| ithub.com/whazor/bca8b687e26081e77d818bc26033c...
|
| Nix helps Claude a lot with dependencies, it can add stuff
| and execute the flake as well.
|
| I will come back to you with project itself.
| firesteelrain wrote:
| Can you explain TUI? I have never heard this before
| ses1984 wrote:
| Terminal UI.
| Bjartr wrote:
| Terminal User Interface, contrasting with a Graphical User
| Interface (GUI). Most often applied to programs that use the
| terminal as a pseudo-graphical canvas that they draw on with
| characters to provide an interactive page that can be
| navigated around with the keyboard.
|
| Really, they're just a GUI drawn with Unicode instead of
| drawing primitives.
|
| Like many restrictions, limiting oneself to just a fixed grid
| of colored Unicode characters for drawing lends itself to
| more creative solutions to problems. Some people prefer such
| UIs, some people don't.
| Muvasa wrote:
| I prefer tui's for two reasons. 1. Very used to vi
| keybindings 2. I like low resources software. I love the
| ability to open the software in less than a second in a
| second do what I needed using vi motions. And close it less
| than a second.
|
| Some people will be like you save two seconds trying to do
| something simple. You lose more time building the tool than
| you will use it in your life.
|
| It's not about saving time. It's about eliminating the
| mental toll from having to context switch(i know it sounds
| ai, reading so much ai text has gotten to me)
| irl_zebra wrote:
| "It's not about saving time, it's about eliminating the
| mental toll from having to context switch"
|
| This broke my brain! Woah!
| kstrauser wrote:
| That's an excellent way to explain it. I'm already in the
| shell doing stuff. Whenever I can stay there without
| sacrificing usability, it's a big boost.
| criddell wrote:
| > an interactive page that can be navigated around with the
| keyboard
|
| Or mouse / trackpad.
|
| I really haven't seen anything better for making TUIs than
| Borland's Turbo Vision framework from 35ish years ago.
| GCUMstlyHarmls wrote:
| Eg: lazygit
| https://github.com/jesseduffield/lazygit?tab=readme-ov-
| file#... https://github.com/sxyazi/yazi
| https://github.com/darrenburns/posting or I guess _Vim_ would
| be a prominent example.
|
| Peoples definitions will be on a gradient, but its somewhere
| between CLI (type into a terminal to use) and GUI (use your
| mouse in a windowing system), TUI runs in your terminal like
| a CLI but probably supports "graphical widgets" like buttons,
| bars, hotkeys, panes, etc.
| giglamesh wrote:
| So the acronym is for Terrible User Interface? ;)
| allarm wrote:
| No it's not.
| worksonmine wrote:
| TUI is peak UI, anyone who disagrees just don't get it.
| Every program listens to the same keybindings, looks the
| same and are composable to work together. You don't get
| that clicking buttons with the mouse. It's built to get
| the work done not look pretty.
| booleandilemma wrote:
| It's definitely an acronym that got popular in the last year
| or so, though I'm sure there are people out there who will
| pretend otherwise. I've been in the industry 15+ years now
| and never heard it before. Previously it was just UI, GUI, or
| CLI.
| freedomben wrote:
| It's gotten more popular for sure, but it's definitely been
| around a long time. Even just on HN there have been
| conversation about gdb tui ever since I've been here
| (starting browsing HN around 2011). For anyone who works in
| embedded systems it's a very common term and has been since
| I got into it in 2008-ish. I would guess it was much more
| of a linux/unix user thing until recently though, so people
| on windows and mac probably rarely if ever intersected with
| the term, so that's definitely a change. Just my
| observations.
| snozolli wrote:
| As someone who came up using Borland's Turbo Pascal, Turbo
| C, and Turbo Vision (their OOP UI framework), it was called
| CUI (character-based user interface) to distinguish from
| GUI, which became relevant as Windows became dominant.
|
| I never heard "TUI" until the last few years, but it may be
| due to my background being Microsoft-oriented.
|
| One of the only references I can find is the PC Magazine
| encyclopedia: https://www.pcmag.com/encyclopedia/term/cui
| 0x1ch wrote:
| My friends and I have been actively in the "CLI/TUI" since
| middle school. Anyone tinkering on linux that used tiling
| window managers is already very familiar with the domain.
| layer8 wrote:
| https://en.wikipedia.org/wiki/Text-based_user_interface
| hattmall wrote:
| What are some examples of useful TUI you made? I'm generally
| opposed to the concept
| rw_panic0_0 wrote:
| how do you trust the code claude wrote? don't you get anxiety
| "what if there's an error in tui code and it would mess up my
| git repo"?
| sclangdon wrote:
| Isn't it this case no matter who wrote the code? How do you
| ever run anything if you're worried about bugs?
| phailhaus wrote:
| When I write the code myself, I'm not worried that I snuck
| a `git reset --hard` somewhere.
| hennell wrote:
| Different type of creator, different type of bugs. I'd
| assume a human giving me a way to delete merged branches
| has probably had the same issue, solved the same problem
| and understands unspecified context around the problem (e.g
| protect local data). They probably run it themselves so
| bugs are most likely to occur in edge cases around none
| standard use as it works for them.
|
| Ais are giving you what they get from common patterns,
| parsing documentation etc. Depending what you're asking
| this might be an entirely novel combination of commands
| never run before. And depending on the model/prompt it
| might solve in a way any human would balk at (push main to
| origin, delete .git, re-clone from origin. Merged local
| branches are gone!)
|
| It's like the ai art issues - people struggle with relative
| proportions and tones and making it look real. Ai has no
| issues with tones, but will add extra fingers or arms etc
| that humans rarely struggle with. You have to look for
| different things, and Ai bugs are definitely more dangerous
| than (most _) human bugs.
|
| (_Depends a little, it's pretty easy to tell if a human
| knows what they're talking about. There's for sure humans
| who could write super destructive code, but other elements
| usually make you suspicious and worried about the code
| before that)
| layer8 wrote:
| It makes a difference whether an AI or a human wrote it.
| AIs make more random, inconsistent errors or omissions that
| a human wouldn't make. AIs also don't dog-feed their code
| the way human developers of tools usually do, catching more
| errors or unfit/missing logic that way.
| embedding-shape wrote:
| > how do you trust the code claude wrote?
|
| If that's something you're worried about, review the code
| before running it.
|
| > don't you get anxiety "what if there's an error in tui code
| and it would mess up my git repo"?
|
| I think you might want to not run untrusted programs in an
| environment like that, alternatively find a way of start
| being able to trust the program. Either approaches work, and
| works best depending on what you're trying to do.
| kaoD wrote:
| > If that's something you're worried about, review the code
| before running it.
|
| It takes _more_ , not less, time to thoroughly review code
| you didn't write.
| embedding-shape wrote:
| Depends. If I was the one coming up with the
| implementation anyways, it's basically just the "coding"
| part that was replaced with "fingers hitting keyboard"
| and "agents writing to disk", so reviewing the code
| certainly is faster, you just have to "check" it, not
| understand it from scratch.
|
| If we're talking receiving random patches where first you
| have to understand the context, background and so on,
| then yeah I agree, it'll take longer time probably than
| what it took for someone to hammer with their fingers.
| But again, I'm not sure that's how professionals use LLMs
| right now, vibe-coding is a small hyped world mostly non-
| programmers seem to engage in.
| kaoD wrote:
| > you just have to "check" it, not understand it from
| scratch.
|
| How can you "check" that which you don't "understand"?
|
| > I'm not sure that's how professionals use LLMs right
| now
|
| I'm a professional and I can tell you how I use LLMs: I
| write code with their assistance, they don't write code
| for me.
|
| The few times I let Claude or Copilot loose, the results
| were heartbreaking and I spent more time reviewing (and
| then discarding) the code than what it took me to later
| write it from scratch.
| embedding-shape wrote:
| > How can you "check" that which you don't "understand"?
|
| ??? I do understand, since I literally just instructed
| it, how would I otherwise? I'm not letting the LLM do the
| design, it's all me still. So the "understand" already
| exists before the LLM even finished working.
|
| > I'm a professional and I can tell you how I use LLMs: I
| write code with their assistance, they don't write code
| for me.
|
| Hey, welcome to the club, me too :) I don't write code, I
| write English prose, yet nothing is vibe coded, and
| probably I'll end up being able to spend more time than
| you thinking about the design and architecture and how it
| fits in, because actual typing is no longer slowing me
| down. Yet again, every line is reviewed multiple times.
|
| It's more about the person behind the tools, than the
| tools themselves I think ultimately. Except for Copilot
| probably, the times I've tried it I've just not been able
| to produce code that is even slightly up to my standards.
| It's a breeze with Codex though (5.2), and kind of hit
| and miss with Claude Code.
| freedomben wrote:
| I'm not GP, but I have backups, plus I always make sure I've
| committed and pushed all code I care about to the remote. I
| do this even when running a prompt in an agent. That goes for
| running most things actually, not just CC. If claude code
| runs a git push -f then that could really hurt, but I have
| enough confidence from working with the agents that they
| aren't going to do that that it's worth it to me to take the
| risk in exchange for the convenience of using the agent.
| ithkuil wrote:
| I assume that whatever I type can be also flawed and take
| precautions like backups etc
| whazor wrote:
| I push my branches daily, so I wouldn't lose that much work.
| If it breaks then I ask it to fix it.
|
| But I do quickly check the output what it does, and
| especially the commands it runs. Sometimes it throws all code
| in a single file, so I ask for 'good architecture with
| abstractions'.
| zenoprax wrote:
| I see this regularly: "I use GitHub to backup my local
| repos."
|
| If `gh repo ...` commands get run you can lose everything
| instantly. You can force push and be left with a single
| blank commit on both sides. The agent has full control of
| everything, not just your local data.
|
| Just set up Rclone/restic and get your stuff into a system
| with some immutability.
| tux1968 wrote:
| Force pushing doesn't actually remove anything from the
| remote repository, only changes some references for which
| commits the branches point to. Plus, any forks on github
| will be completely unaffected. It's not perfect, since
| Github doesn't seem to offer any history of such
| reference alterations (a la the reflog), but it's still a
| valuable offsite backup from a developer's perspective.
| fragmede wrote:
| It's a git repo. What's sort of mess-ups are you worried
| about that you can't reflog your way out of (or ask claude
| code to fix)? It's certainly possible to lose uncommitted
| work, but once it's been committed, unless claude code goes
| and deletes .git entirely (which I've had codex do, so you'd
| better push it somewhere), you can't lose work.
| eulers_secret wrote:
| Tig is a nice and long-maintained git tui you might enjoy,
| then!
|
| If nothing else maybe for inspiration
| kqr wrote:
| In the case of Git, I can warmly recommend Magit as a TUI. Not
| only does it make frequent operations easier and rare
| operations doable -- it also teaches you Git!
|
| I have a draft here about one aspect of Magit I enjoy:
| https://entropicthoughts.com/rebasing-in-magit
| galbar wrote:
| The git plugin in oh-my-zsh has an alias for this: gbda
|
| It also has one for squash-merged branches: gbds
|
| Very useful I've been using them for years
| blakesterz wrote:
| That's handy! I just started using oh-my-zsh and I feel like I
| know about 4% of useful things it can do so far.
| gjvc wrote:
| "trapd00r" is the theme you want, if only because the name is
| cool
| giglamesh wrote:
| I change themes just often enough to completely forget how
| to do it and also forget whatever other adjustments I had
| to make to it all work. And like... is my config versioned
| somehow? This is a long way to say, Thank You for inspiring
| me to look at all that stuff again!
| parliament32 wrote:
| So effectively "I just discovered xargs"? Not to disparage OP but
| there isn't anything particularly novel here.
| jimmydoe wrote:
| And they have to learn that from cia?
|
| That says so much about the generation we are in, just don't go
| to school but learn math from mafia
| vntok wrote:
| Where else would you learn about triple-entry bookkeeping?
| skydhash wrote:
| People really do need to read the "Unix Power Tools" book and
| realize their problem has been solved for decades.
| gosub100 wrote:
| "People just need to find the info they don't know about, so
| then they'll know it."
| SoftTalker wrote:
| People need to be curious. Then they seek out the info they
| don't know about.
| gavinray wrote:
| I don't find that the insinuation of the parent comment at
| all.
|
| Saying "If you read X book, you'll realize it's a solved
| problem" IS the information -- the name of the book you
| need to read
| Someone1234 wrote:
| This feels like gatekeeping someone sharing something cool
| they've recently learned.
|
| I personally lean more towards the "let's share cool little
| productivity tips and tricks with one another" instead of the
| "in order to share this you have to meet [entirely arbitrary
| line of novelty/cleverness/originality]."
|
| But each to their own I suppose. I wonder how _you_ learned
| about using xargs? Maybe a blog-post or article not dissimilar
| to this one?
| superxpro12 wrote:
| No I agree with you. This whole aura of "well IIIII knew this
| and YOUUUUU didnt" needs to die. I get that it's sometimes
| redundant and frustrating to encounter the same question a
| few times... but there's always new people learning in this
| world, and they deserve a chance to learn too.
|
| Why do people constantly have to be looking for any way to
| justify their sense of superiority over others? Collaborative
| attitudes are so much better for all involved.
| parliament32 wrote:
| I don't think there's anything wrong with sharing something
| cool, even if it's trivial to other people. The problem is
| framing a blog post with "ooh this was buried in the secret
| leaked CIA material".. and then the reader opens it to find
| out it's just xargs. It feels very clickbaity. Akin to
| "here's one simple trick to gain a treasure trove of
| information about all the secret processes running on your
| system!!" and it's just ps.
| audience_mem wrote:
| It felt almost like satire to me, especially with the name
| "ciaclean".
| ggrab wrote:
| Lots of negative sentiment on your comment, but I was going to
| write the same. Hopefully AI won't make us forget that good
| command line tools are designed to be chained together if you
| want to achieve something that's perhaps too niche as a use
| case to make it into a native command. It's worth learning
| about swiss army utilities like xargs that make this easy (and
| fun)
| mrexcess wrote:
| Seriously, this seems like someone in awe of xargs. Maybe its
| the Bell Labs in me but this is boilerplate stuff.
| oldestofsports wrote:
| It's cool that it comes from CIA, and someone who doesn't know
| about xargs may just learn something new. What is not to like?
| dewey wrote:
| If you are using Fork.app on Mac as your git client, this now
| exists (For one month now) there too: https://github.com/fork-
| dev/Tracker/issues/2200#issuecomment...
| sigio wrote:
| I've had this command as 'git drop-merged' for a few years now
| (put as a script in your path named git-drop-merged:
| #!/bin/sh git branch --merged | egrep -v
| "(^\*|master|main|dev)" | xargs --no-run-if-empty git
| branch -d
| 1a527dd5 wrote:
| I use #!/bin/sh git checkout
| main git fetch --prune git branch | grep -v main
| | xargs --no-run-if-empty git branch -D git pull
|
| Save that next to your git binary, call it whatever you want.
| It's destructive on purpose.
| arusahni wrote:
| I use this alias: prune-local = "!git fetch -p
| && for branch in $(git branch -vv | awk '/: gone]/{if
| ($1!=\"\*\") print $1}'); do git branch -d $branch; done"
|
| 1. Fetch the latest from my remote, removing any remote tracking
| branches that no longer exist
|
| 2. Enumerate local branches, selecting each that has been marked
| as no longer having a remote version (ignoring the current
| branch)
|
| 3. Delete the local branch safely
| gritzko wrote:
| Speaking of user friendliness of git UI. I am working on a
| revision control system that (ideally) should be as user friendly
| as Ctrl+S Ctrl+Z in most common cases. Spent almost a week on
| design docs, looking for feedback (so far it was very valuable,
| btw)
|
| https://replicated.wiki/blog/partII.html#navigating-the-hist...
| oniony wrote:
| Have you tried Jujutsu? If you want to make a better VCS, your
| baseline should be that, in my opinion, because it already
| deals with a lot of the Git pain points whilst be able to read
| and publish to Git repositories.
| gritzko wrote:
| The idea of using git as a blob storage and building entire
| new machinery on top is definitely a worthy one. At this
| point though, the de-facto baseline is no doubt git. If git
| as a store withstands the abuse of jj and jj becomes the
| industry standard, then I would agree with you. Also, at that
| point they may drop git backend entirely just because of
| price/performance discrepancy. git is overweight for what it
| does, if they make it do only the bottom 20%, then things
| will get funny.
|
| Still, many oddities of git are inevitable due to its
| underlying storage model, so it makes sense to explore other
| models too.
| jo-m wrote:
| I have something similar, but open fzf to select the branches to
| delete [1]. function fcleanb -d "fzf git select
| branches to delete where the upstream has disappeared"
| set -l branches_to_delete ( git for-each-ref
| --sort=committerdate --format='%(refname:lstrip=2)
| %(upstream:track)' refs/heads/ | \ egrep
| '\[gone\]$' | grep -v "master" | \ awk '{print
| $1}' | $_FZF_BINARY --multi --exit-0 \ )
| for branch in $branches_to_delete git branch -D
| "$branch" end end
|
| [1]:
| https://github.com/jo-m/dotfiles/blob/29d4cab4ba6a18dc44dcf9...
| lloeki wrote:
| I've had essentially that - if a bit fancier to accept an
| optional argument as well as handle common "mainline" branch
| names - aliased as `git lint` for a while:
| [alias] lint = !git branch --merged ${1-} | grep -v
| -E -e '^[*]?[ ]*(main|master|[0-9]+[.]([0-9]+|x)-stable)$' -e
| '^[*][ ]+' | xargs -r -n 1 git branch --delete
|
| so: git pull --prune && git lint
|
| sits very high in my history stats
| jakub_g wrote:
| The main issue with `git branch --merged` is that if the repo
| enforces squash merges, it obviously won't work, because SHA of
| squash-merged commit in main != SHA of the original branch HEAD.
|
| What tools are the best to do the equivalent but for squash-
| merged branches detections?
|
| Note: this problem is harder than it seems to do safely, because
| e.g. I can have a branch `foo` locally that was squash-merged on
| remote, but before it happened, I might have added a few more
| commits locally and forgot to push. So naively deleting `foo`
| locally may make me lose data.
| masklinn wrote:
| Not just squash merges, rebase-merges also don't work.
|
| > What tools are the best to do the equivalent but for squash-
| merged branches detections?
|
| Hooking on remote branch deletion is what most people do, under
| the assumption that you tend to clean out the branches of your
| PRs after a while. But of course if you don't do that it
| doesn't work.
| WorldMaker wrote:
| This is my PowerShell variant for squash merge repos:
| function Rename-GitBranches { git branch --list
| "my-branch-prefix/*" | Out-GridView -Title "Branches to Zoo?"
| -OutputMode Multiple | % { git branch -m $_.Trim()
| "zoo/$($_.Trim())" } }
|
| `Out-GridView` gives a very simple dialog box to (multi) select
| branch names I want to mark finished.
|
| I'm a branch hoarder in a squash merge repo and just prepend a
| `zoo/` prefix. `zoo/` generally sorts to the bottom of branch
| lists and I can collapse it as a folder in many UIs. I have
| found this useful in several ways:
|
| 1) It makes `git rebase --interactive` much easier when working
| with stacked branches by taking advantage of `--update-refs`.
| Merges do all that work for you by finding their common
| base/ancestor. Squash merging you have to remember which
| commits already merged to drop from your branch. With
| `--update-refs` if I find it trying to update a `zoo/` branch I
| know I can drop/delete every commit up to that update-ref line
| and also delete the update-ref.
|
| 2) I sometimes do want to find code in intermediate commits
| that never made it into the squashed version. Maybe I tried an
| experiment in a commit in a branch, then deleted that
| experiment in switching directions in a later commit. Squashing
| removes all evidence of that deleted experiment, but I can
| still find it if I remember the `zoo/` branch name.
|
| All this extra work for things that merge commits gives you for
| free/simpler just makes me dislike squash merging repos more.
| samhclark wrote:
| Depends on your workflow, I guess. I don't need to handle that
| case you noted and we delete the branch on remote after it's
| merged. So, it's good enough for me to delete my local branch
| if the upstream branch is gone. This is the alias I use for
| that, which I picked up from HN. #
| ~/.gitconfig [alias] gone = ! "git fetch -p
| && git for-each-ref --format '%(refname:short)
| %(upstream:track)' | awk '$2 == \"[gone]\" {print $1}' | xargs
| -r git branch -D"
|
| Then you just `git gone` every once in a while, when you're
| between features.
| laksdjf wrote:
| I have the same issue. Changes get pushed to gerrit and rebased
| on the server. This is what I have, though not perfected yet.
| prunable = "!f() { \ : git log ; \ target=\"$1\"; \
| [ -z \"$target\" ] && target=$(git for-each-ref
| --format=\"%(refname:short)\" --count=1 refs/remotes/m/); \
| if [ -z \"$target\" ]; then echo \"No remote branches found in
| refs/remotes/m/\"; return 1; fi; \ echo \"# git branch
| --merged shows merged if same commit ID only\" ;\ echo
| \"# if rebased, git cherry can show branch HEAD is merged\" ;\
| echo \"# git log grep will check latest commit subject only.
| if amended, this status won't be accurate\" ;\ echo \"#
| Comparing against $target...\"; \ echo \"# git branch
| --merged:\"; \ git branch --merged $target ;\ echo
| \" ,- git cherry\" ; \ echo \" | ,- git log grep latest
| message\"; \ for branch in $(git for-each-ref
| --format='%(refname:short)' refs/heads/); do \ if git
| cherry \"$target\" \"$branch\" | tail -n 1 | grep -q \"^-\";
| then \ cr=""; \ else \ cr=""; \
| fi ; \ c=$(git rev-parse --short $branch) ; \
| subject=$(git log -1 --format=%s \"$branch\" | sed
| 's/[][(){}.^$\*+?|\\/]/\\\\&/g') ; \ if git log
| --grep=\"^$subject$\" --oneline \"$target\" | grep -q .; then \
| printf \"$cr $c %-20s $subject\\n\" $branch; \ else \
| printf \"$cr \\033[0;33m$c \\033[0;32m%-20s\\033[0m
| $subject\\n\" $branch; \ fi; \ done; \ };
| f"
|
| (some emojis missing in above. see gist)
| https://gist.github.com/lawm/8087252b4372759b2fe3b4052bf7e45...
|
| It prints the results of 3 methods:
|
| 1. git branch --merged
|
| 2. git cherry
|
| 3. grep upstream git log for a commit with the same commit
| subject
|
| Has some caveats, like if upstream's commit was amended or the
| actual code change is different, it can have a false positive,
| or if there are multiple commits on your local branch, only the
| top commit is checked
| arccy wrote:
| if you're using gerrit then you have the Change-Id trailer
| you can match against?
| de46le wrote:
| Mine's this-ish (nushell, but easily bashified or pwshd) for
| finding all merged, including squashed: let t
| = "origin/dev"; git for-each-ref refs/heads/
| --format="%(refname:short)" | lines | where {|b| $b !~ 'dev'
| and (git merge-tree --write-tree $t $b | lines | first) == (git
| rev-parse $"($t)^{tree}") }
|
| Does a 3-way in-mem merge against (in my case) dev. If there's
| code in the branch that isn't in the target it won't show up.
|
| Pipe right to deletion if brave, or to a choice-thingy if
| prudent :)
| otsaloma wrote:
| I recently revised my script to rely on (1) no commits in the
| last 30 days and (2) branch not found on origin. This is
| obviously not perfect, but it's good enough for me and just in
| case, my script prompts to confirm before deleting each branch,
| although most of the time I just blindly hit yes.
|
| To avoid losing any work, I have a habit of never keeping
| branches local-only for long. Additionally this relies on
| https://docs.github.com/en/repositories/configuring-branches...
| Arch-TK wrote:
| Unfortunately doesn't work if the project you work on squashes
| everything :(
| schiffern wrote:
| "ciaclean" is a nice touch.
|
| I assume CIA stands for Clean It All.
| sammyteee wrote:
| "Clean It All, Clean" :P
| plufz wrote:
| I assume it means mess up commit history and install "our"
| BDFL.
| stabbles wrote:
| Missed opportunity to call it `git ciao`
| trashymctrash wrote:
| If you squash your PR before merging, then this alternative
| worked really well for me: git fetch --prune &&
| git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -D
| lkbm wrote:
| Almost identical to mine, but you've got smarter awk use: `git
| prune origin && git branch -vv | grep 'origin/.*: gone]' | awk
| '{print $1}' | xargs git branch -D`
|
| I think I probably copied this from Stack Overflow close to a
| decade ago. Seems like a lot of people have very similar
| variations.
| taude wrote:
| I've had this in my ~/.bash_aliases for awhile:
| alias git-wipe-merged-branches='git branch --merged | grep -v \*
| | xargs git branch -D'
|
| Trying to remember where I got that one, as I had commented the
| following version out: alias git-wipe-all-
| branches='git for-each-ref --format '%(refname:short)' refs/heads
| | grep -v master | xargs git branch -D'
| Cherub0774 wrote:
| We all have something similar, it seems! I stole mine from
| https://stackoverflow.com/questions/7726949/remove-tracking-....
|
| I also set mine up to run on `git checkout master` so that I
| don't really have to think about it too hard -- it just runs
| automagically. `gcm` has now become muscle memory for me.
| alias gcm=$'git checkout master || git checkout main && git pull
| && git remote prune origin && git branch -vv | grep \': gone]\'|
| grep -v "\*" | awk \'{ print $1; }\' | xargs -r git branch -D'
| masklinn wrote:
| Same using a git alias rather than shell, and without the
| network bits, it just cleans up branches which have an upstream
| that has been deleted: '!f() { git branch
| --format '%(refname:short) %(upstream:track,nobracket)' | awk
| '$2~/^gone$/{print $1}' | xargs git branch -D; }; f'
| d0liver wrote:
| IIRC, you can do git branch -D $(git branch) and git will refuse
| to delete your current branch. Kind of the lazy way. I never work
| off of master/main, and usually when I need to look at them I
| checkout the remote branches instead.
| dietr1ch wrote:
| Wait, why would the update for the silly master->main change be
| swapping the excluded regex instead of just excluding both?
| PunchyHamster wrote:
| coz OP has agenda and
|
| > Since most projects now use main instead of master
|
| some delusions to boot
| Sesse__ wrote:
| You probably want git-dmb (dmb = delete merged branches) for a
| safe and more comprehensive way of dealing with this.
| puzz wrote:
| Or git-old-branches/git-recent from git-plus
|
| https://github.com/tkrajina/git-plus
|
| Disclaimer, I'm the author ^^
| ihsoy wrote:
| Dont most git instances, like github, delete branch after a PR
| was merged, by default?
|
| I am not sure under what usecases, you will end up with a lot of
| stale branches. And git fetch -pa should fix it locally
| plqbfbv wrote:
| In Github it needs to be explicitly configured (Settings >
| General > Delete head branches after merging), Gitlab is the
| same.
|
| A lot of my developer colleagues don't know how git works, so
| they have no idea that "I merged the PR" != "I deleted the
| feature branch". I once had to cleanup a couple repositories
| that had hundreds of branches spanning back 5+ years.
|
| Nowadays I enforce it as the default project setting.
| nightpool wrote:
| `--prune` will delete your local copies of the _origin 's_
| branches (e.g. `origin/whatever`). But it won't delete your
| _local_ branches (e.g. `whatever` itself). So PRs that you 've
| worked on or checked out locally will never get deleted.
| embedding-shape wrote:
| > Dont most git instances, like github, delete branch after a
| PR was merged, by default?
|
| By default, I don't think so. And even if the branch is
| deleted, objects can still be there. I think GitLab has a
| "Clean stale objects" thing you can trigger, I don't seem to
| recall ever seeing any "Git Maintenance" UI actions on GitHub
| so not sure how it works there.
| micw wrote:
| I recently let copilot create a document with a few helpful git
| commands and that particular one was the one it came with as
| solution for exactly this case.
| password4321 wrote:
| I don't delete branches, I just work with the top several most
| recently modified.
| the_real_cher wrote:
| How to list those? Is there a flag for git branch to sort by
| recently modified?
|
| (not on my computer right now to check)
| embedding-shape wrote:
| I do `gb` (probably "git branch" when I set that up) which
| apparently is an alias to `git for-each-ref
| --sort=-committerdate refs/heads/ --format='%(refname:short)'
| | tac`, displays a list with the latest changed branch at the
| bottom. Remove the `| tac` for the reverse order.
| password4321 wrote:
| Yes, I run something like this (PowerShell borks out unless
| there are double quotes inside the single quotes) in a
| short script when I need to review available branches:
| git fetch --all --prune --quiet git log origin/main
| --date=format:%m%d%H%M
| --pretty=format:'%C(yellow)%ad-%h%C(auto)%d %s (%cn)' -n1
| git log --tags --date=format:%m%d%H%M
| --pretty=format:'%C(yellow)%ad-%h%C(auto)%d %s (%cn)' -n1
| echo '' git for-each-ref --count=10
| --sort=-committerdate refs/heads/ --format='%(color:yellow)
| %(committerdate:format:%m%d%H%M)-%(objectname:short)
| (%(color:green)%(refname:short)%(color:yellow))
| %(color:white)%(contents:subject) (%(authorname))'
|
| I include a [month][day][hour][minute]-[git hash] prefix as
| enough info to see when branches were last updated and grab
| them when I make a mistake creating the branch from the
| wrong parent or want to cherry-pick.
| rpozarickij wrote:
| This isn't exactly the same but I've been using git-recent
| [0] (with `gr` alias) for many years. It sorts branches based
| on checkout order (which is what I usually need when
| switching between branches) and allows to easily choose a
| branch to checkout to.
|
| [0] https://github.com/paulirish/git-recent
| jimnotgym wrote:
| I have an image of running his command, 'ciaclean', and a black
| van turnes up with a bunch of agents in coveralls, brandishing
| rolls of polyethylene sheeting and drums of acid.
| EricRiese wrote:
| Much more complicated than necessary. I just use
|
| git branch | xargs git branch -d
|
| Don't quote me, that's off the top of my head.
|
| It won't delete unmerged branches by default. The line with the
| marker for the current branch throws an error but it does no
| harm. And I just run it with `develop` checked out. If I delete
| develop by accident I can recreate it from origin/develop.
|
| Sometimes I intentionally delete develop if my develop branch is
| far behind the feature branch I'm on. If I don't and I have to
| switch to a really old develop and pull before merging in my
| feature branch, it creates unnecessary churn on my files and
| makes my IDE waste time trying to build the obsolete stuff. And
| depending how obsolete it is and what files have changed, it can
| be disruptive to the IDE.
| cowlby wrote:
| Anyone else "vibe git-ing" lately? I just ask Claude Opus to
| clean it up and it does really well. Same for build commands and
| test harnesses.
| mywittyname wrote:
| It does a pretty good job, but I still don't completely trust
| it with keys to the kingdom.
|
| I have replaced my standard ddg of, "git <the thing i need>"
| with asking Claude to give me the commands I need to run.
| WickyNilliams wrote:
| I have a cleanup command that integrates with fzf. It pre selects
| every merged branch, so I can just hit return to delete them all.
| But it gives me the opportunity to deselect to preserve any
| branches if I want. It also prunes any remote branches
| # remove merged branches (local and remote) cleanup =
| "!git branch -vv | grep ': gone]' | awk '{print $1}' | fzf
| --multi --sync --bind start:select-all | xargs git branch -D; git
| remote prune origin;"
|
| https://github.com/WickyNilliams/dotfiles/blob/c4154dd9b6980...
|
| I've got a few aliases that integrate with fzf like an
| interactive cherry pick (choose branch, choose 1 or more
| commits), or a branch selector with a preview panel showing
| commits to the side. Super useful
|
| The article also mentions that master has changed to main mostly,
| but some places use develop and other names as their primary
| branch. For that reason I always use a git config variable to
| reference such branches. In my global git config it's main. Then
| I override where necessary in any repo's local config eg here's
| an update command that updates primary and rebases the current
| branch on top: # switch to primary branch,
| pull, switch back, rebase update = !"git switch
| ${1:-$(git config user.primaryBranch)}; git pull; git switch -;
| git rebase -;"
|
| https://github.com/WickyNilliams/dotfiles/blob/c4154dd9b6980...
| lloeki wrote:
| > For that reason I always use a git config variable to
| reference such branches. In my global git config it's main
| $(git config user.primaryBranch)
|
| What about using git's own `init.defaultBranch`?
|
| I mean, while useless in terms of `git init` because the repo's
| already init'd, this works: git config
| --local init.defaultBranch main
|
| And if you have `init.defaultBranch` set up already globally
| for `git init` then it all just works
| WickyNilliams wrote:
| Hmm that might be nice actually. I like not conflating those
| two things, but as you say if the repo is already init'd then
| there's no chance it'll be used for the wrong purpose.
|
| In any case the main thrust was just to avoid embeddings
| assumptions about branch names in your scripts :)
| MathiasPius wrote:
| You can pull another branch without switching first:
| git switch my-test-branch ... git pull origin
| main:main git rebase main
| WickyNilliams wrote:
| Nice. That'll make things a bit smoother. Changing branches
| often trips me up when I would later `git switch -`.
| huntervang wrote:
| I have always done `git pull origin main -r`
| mroche wrote:
| Likewise with the other way around, just switch pull with
| push.
| hiccuphippo wrote:
| You can also rebase directly on the remote branch
| git fetch git rebase origin/main
| devhouse wrote:
| don't forget to fetch first
| nikeee wrote:
| I use git-trim for that:
|
| https://github.com/foriequal0/git-trim
|
| Readme also explains why it's better than a bash-oneliner in some
| cases.
| block_dagger wrote:
| I cleanup branches interactively with a few lines of bash, which
| takes a bit more time but is less likely to destroy active work.
| WorldMaker wrote:
| I use this PowerShell variant: function Remove-
| GitBranches { git branch --merged | Out-GridView
| -Title "Branches to Remove?" -OutputMode Multiple | % { git
| branch -d $_.Trim() } }
|
| `Out-GridView` gives you a quick popup dialog with all the branch
| names that supports easy multi-select. That way you get a quick
| preview of what you are cleaning up and can skip work in progress
| branch names that you haven't committed anything to yet.
| markus_zhang wrote:
| Oh this is what ChatGPT told me when I asked "How to remove all
| local branch except main"...
| maerF0x0 wrote:
| DEFAULT_BRANCH=$(git remote show origin | sed -n '/HEAD
| branch/s/.*: //p') git branch --merged
| "origin/$DEFAULT_BRANCH" \ | grep -vE
| "^\s*(\*|$DEFAULT_BRANCH)" \ | xargs -r -n 1 git branch
| -d
|
| This is the version I'd want in my $EMPLOYER's codebase that has
| a mix of default branches
| rickknowlton wrote:
| honestly my go to is kind of similar, but I prefer using --format
| vs. straight grep. just feels like the plumbing is cleaner out of
| the box: git branch --merged origin/main
| --format="%(refname:short)" \ | grep -vE "^(main|develop)$" \ |
| xargs -r git branch -d
|
| that said... pretty hilarious a dev was just like "uhh yeah
| ciaclean..." curious what... other aliases they might have??
| coderpersson wrote:
| `git trash`
|
| https://github.com/henrikpersson/git-trash
|
| I use this script with a quick overview to prevent accidentally
| deleting something important
| mrbonner wrote:
| > Since most projects now use main instead of master...
|
| I see that even the CIA, a federal government office, has not
| fully used DEI approved, inclusive language yet :-)
| jen20 wrote:
| The leaked material from which this came was described as being
| from 2017, which makes that the latest this could have been
| written - GitHub only changed the default for new repos in
| October of 2020, and there had only been consensus building
| around the switch for a couple of years beforehand.
| gritzko wrote:
| If something this natural requires several lines of bash,
| something is just not right. Maybe branches should go sorted by
| default, either chronologically or topologically? git's LoC
| budget is 20x LevelDBs or 30% of PostgreSQL or 3 SQLites. It must
| be able to do these things out of the box, isn't it?
|
| https://replicated.wiki/blog/partII.html
| cloudfudge wrote:
| "too many lines of bash" and "lines of code" seem like very
| strange metrics to use to form these types of opinions.
| fphilipe wrote:
| Here's my take on the one-liner that I use via a `git tidy`
| alias[1]. A few points:
|
| * It ensures the default branch is not deleted (main, master)
|
| * It does not touch the current branch
|
| * It does not touch the branch in a different worktree[2]
|
| * It also works with non-merge repos by deleting the local
| branches that are gone on the remote git branch
| --merged "$(git config init.defaultBranch)" \ | grep -Fv
| "$(git config init.defaultBranch)" \ | grep -vF '*' \
| | grep -vF '+' \ | xargs git branch -d \ && git
| fetch \ && git remote prune origin \ && git
| branch -v \ | grep -F '[gone]' \ | grep -vF '*' \
| | grep -vF '+' \ | awk '{print $1}' \ | xargs git
| branch -D
|
| [1]:
| https://github.com/fphilipe/dotfiles/blob/ba9187d7c895e44c35...
|
| [2]: https://git-scm.com/docs/git-worktree
| rubinlinux wrote:
| The use of init.defaultBranch here is really problematic,
| because different repositories may use a different name for
| their default, and this is a global (your home directory scope)
| setting you have to pre-set.
|
| I have an alias I use called git default which works like this:
| default = !git symbolic-ref refs/remotes/origin/HEAD | sed
| 's@^refs/remotes/origin/@@'
|
| then it becomes ..."$(git default)"...
|
| This figures out the actual default from the origin.
| fphilipe wrote:
| I have a global setting for that. Whenever I work in a repo
| that deviates from that I override it locally. I have a few
| other aliases that rely on the default branch, such as
| "switch to the default branch". So I usually notice it quite
| quickly when the value is off in a particular repo.
| jeffrallen wrote:
| This is a great solution to a stupid problem.
|
| I work at a company that was born and grew during the
| master->main transition. As a result, we have a 50/50 split
| of main and master.
|
| No matter what you think about the reason for the transition,
| any reasonable person must admit that this was a stupid, user
| hostile, and needlessly complexifying change.
|
| I am a trainer at my company. I literally teach git. And: I
| have no words.
|
| Every time I decide to NOT explain to a new engineer why it's
| that way and say, "just learn that some are master, newer
| ones are main, there's no way to be sure" a little piece of
| me dies inside.
| tonymet wrote:
| This is a good one you should contribute it to git extras.
| devy wrote:
| I needed that exact functionality and Claude code and ChatGPT
| consistently showing this same exact combo CLI receipt with the
| simple prompt "how to do use CLI to remove merged branch
| locally."
| SoftTalker wrote:
| It's hardly a profound insight. If you're fluent at the command
| line, xargs enables all sorts of conveniences.
| bobjordan wrote:
| I use `master` in all my repos because I've been using it since
| forever and it never has once occurred to me "oh shit I better
| change it to `main` this time in case `master` may offend
| somebody some day. Unfortunately, that's the last thing on my
| mind when I'm in programming mode. Now that everything is
| `master`, maybe it is just a simple git command to change it to
| `main`. But, my fear is it'll subtly break something and I just
| don't have enough hours left in my life to accept yet unknown
| risk that it'll cost me even more hours, just to make some random
| sensitive developer not get offended one day.
| kridsdale1 wrote:
| At Meta, when this mass push for the rename happened across the
| industry, a few people spent nearly the full year just
| shepherding the renaming of master to main, and white box/black
| box to allowlist/blocklist.
|
| This let them claim huge diff counts and major contributions to
| DEI and get promos.
| tucnak wrote:
| They measure LoC contributions at FB?
| jihadjihad wrote:
| Same at my org at the time, _blacklist_ was nixed, no matter
| how many times the question, "What color is ink on a page?"
| was brought up.
| layer8 wrote:
| > What color is ink on a page?
|
| Middle gray, according to modern UX designers. ;)
| pmontra wrote:
| You are lucky. It's often light gray on thin fonts.
| pbhjpbhj wrote:
| The colour of the ink is not where "blacklist" comes from
| though? It's not from supposed skin colour either...
|
| Blocklist makes more sense in most scenarios.
| 8organicbits wrote:
| Seems like a bad faith question, unfortunate that it was
| asked multiple times. Blacklist is derived from a
| definition where black means "evil, bad, or undesirable".
| When you say that ink is black, you're using a different
| definition, which relates to color. I don't know if I see
| the objection to blackbox, which uses a definition of
| "unknown". Personally, I think the harm is small but I look
| to people of color for guidance and prefer the more
| descriptive deny-list where I can. Cuts down on possible
| confusion for non-native English speakers too.
| reenorap wrote:
| The irony is that the term "Black" was precisely chosen
| by Black civil rights activists in the 1960s. This wasn't
| a term given by white people, it was specifically chosen
| by Blacks, because of its negative connotations. They
| wanted to embrace its negative connotations and turn it
| on its head, and that's where terms like "Black is
| beautiful" came from. They didn't want to be ashamed of
| it, that's why they embraced it. Black was not a term of
| shame, it was a term of power.
|
| Now, the left wing activists have turned it on its head
| again, and now saying that the term "black" is shameful
| and racist. It's bizarre how ignorant people are who say
| the term "blacklist" is racist.
| yokoprime wrote:
| This is why diffs / LoC is a terrible metric. It shows
| nothing other than a willingness to push large changesets
| upstream.
| joshuamcginnis wrote:
| Also, git's "master" branch is named after a master recording
| or master copy, the canonical original from which duplicates
| are made. There is literally no reason for it be offensive
| except for those who retroactively associate the word with
| slavery.
| imdsm wrote:
| I'll change my default branches to main when Masterclass
| change their name to Mainclass
| zugi wrote:
| And mastering a subject is changed to maining it?
| ffsm8 wrote:
| Yeah, with replica it made a little sense. Was still silly,
| but at least the official master/slave terminology actually
| didn't fully make sense either... So the replica rebrand felt
| justified to me.
|
| With git it was basically entirely driven by SJW that felt
| empowered by people accepting the replica rebrand
| r14c wrote:
| imo the `main` thing was mostly driven by people trying to
| appease the social justice crowd without understanding much
| about the movement. Its a bit of woo in my mind because
| there are still systemic injustices out there that are left
| uncontested, and using main doesn't really contest anything
| substantial.
|
| I don't really care what the default branch is called tho
| so I'm willing to play along.
| ear7h wrote:
| Nope, the term comes from bitkeeper which does refer to
| master/slave.
|
| See this email for some references:
|
| https://mail.gnome.org/archives/desktop-devel-
| list/2019-May/...
| defen wrote:
| I'm fully on-board with not using master-slave terminology.
| I work in the embedded space where those terms were and
| still are frequently used, and I support not using them any
| more. But I've been using git pretty much since it was
| released and I've never heard anyone refer to a "slave
| repo" or "slave branch". It's always been local repo, local
| branch, etc. I fully believe these sorts of digital
| hermeneutics (e.g. using a 26-year-old mailing list post to
| "prove" something, when actual usage is completely
| different) drive division and strife, all because some
| people want to use it to acquire status/prestige.
| themafia wrote:
| Does git use "slave?"
|
| Then does simply performing a search on bitkeepers
| documents for "slave" then automatically imply any
| particular terminology "came from bitkeeper?"
|
| Did they take it from bitkeeper because they prefer
| antiquated chattel slavery terminology? Is there any actual
| documents that show this /intention/?
|
| Or did they take it because "master" without slave is
| easily recognizable as described above which accurately
| describes how it's _actually_ implemented in git.
|
| Further git is distributed. Bitkeeper was not.
|
| This is just time wasting silliness.
| hungryhobbit wrote:
| > But, my fear is it'll subtly break something and I just don't
| have enough hours left in my life to accept yet unknown risk
| that it'll cost me even more hours,
|
| Yeah, it's not like 99% of the world has already switched from
| master to main already (without any major problems) ...
| stevekemp wrote:
| You'll find CI/CD automation _probably_ needs to be updated.
| (Triggering different actions when merges to the default
| branch happen, or perhaps just deployments.)
|
| These are the kinda local things that the parent was probably
| referring to.
| tom_ wrote:
| Thank you for creating the containment thread.
| yokoprime wrote:
| Im just tuning out of the whole master vs main discussion. I
| use whatever is the default branch name of my current project
| OR what git init gives me. When / if git init produces a
| default branch named main, i'll use that.
| botusaurus wrote:
| not on your mind, yet you found the time to write this comment
|
| are you sure this is about time/breaking and not "being told
| how to think"?
| doetoe wrote:
| In current times, there will be more people offended that some
| prefer to use "main" rather than "master", than people that
| will be offended if "master" is used
| drcongo wrote:
| Haven't got enough hours to type fewer characters, but have got
| plenty of time to go karma-fishing about it on an almost barely
| tangentially relevant HN thread. Cool.
| jldugger wrote:
| This looks loosely like something already present in git-
| extras[1]. [1]: https://github.com/tj/git-
| extras/blob/main/Commands.md#git-delete-merged-branches
| bobabob wrote:
| Using grep and xargs is worth a whole blog post now? hmmmmm
| allthetime wrote:
| bash knowledge is probably a quickly dying thing.
|
| hey, gemini, how do I...
| microflash wrote:
| I've been using something similar for years with Nushell.
|
| git branch | lines | where ($it !~ '^*') | each {|br| git branch
| -D ($br | str trim)} | str trim
| samtrack2019 wrote:
| gh-poi plugin is a must if you manage a lot of github pr and want
| to easily clean the branch attached to it when pr is merged
| https://github.com/seachicken/gh-poi
| andrewaylett wrote:
| I keep a command `git-remove-merged`, which uses `git ls-remote`
| to see if the branch is set up to track a remote branch, and if
| it _is_ then whether the remote branch still exists. On the
| assumption that branches which have had remote tracking but no
| longer do are either merged or defunct.
|
| https://gist.github.com/andrewaylett/27c6a33bd2fc8c99eada605...
|
| But actually nowadays I use JJ and don't worry about named
| branches :).
| Svoka wrote:
| I work with GitHub, so this oneliner relly helps me out. It also
| doesn't rely on grep, since --format have all you need:
| git branch --format '%(if:equals=gone)%(upstream:track,nobracket)
| %(then)%(refname:short)%(end)' --omit-empty | xargs --verbose -r
| git branch -D
|
| It deletes all the branches for which remotes were deleted.
| GitHub deletes branches after PR was merged. I alias it to
| delete-merged
| arduanika wrote:
| Trust Langley to neatly tie up all the loose ends.
| tonmoy wrote:
| I'm surprised to see not enough people using xargs, or maybe I
| overuse it
| tpoacher wrote:
| grep + xargs ... in other words, we're finally back at good old
| standard svn workflows
| kazinator wrote:
| Or don't go crazy making branches in the first place.
|
| Have a merge workflow which deletes the branch right there.
| locallost wrote:
| I've used this for about 10 years now. Pretty sure it was a
| widespread way of doing it before any CIA leak.
| andix wrote:
| I sometimes convert old branches to tags. So they don't show up
| in the list of branches, but I never lose any branches by
| accident.
|
| All those "merged" workflows only work, if you actually merge the
| branches. It doesn't work with a squash merge workflow.
|
| edit: I delegate this task to a coding agent. I'm really bad at
| bash commands. yolo!
| renlo wrote:
| I use this tool, which allows one to select the branches to
| delete instead of just deleting everything:
| https://github.com/stefanwille/git-branch-delete
|
| Unfortunately its name makes it hard to search for and find.
| rudnevr wrote:
| What's wrong with just deleting the whole folder and clone repo
| and whatever branch you're interested in? In any case it's not an
| urgent thing. You don't have to do this mid-work, you can wait
| until you push most stuff and then rm && git clone.
|
| The only case in which this wouldn't work is when you have a ton
| of necessary local branches you can't even push to remote, which
| is a risk and anti-pattern per se.
| efficax wrote:
| because of my precious stash? but also the repo is huge, the
| clone takes 10 minutes? And all the other branches...
| 9dev wrote:
| > because of my precious stash?
|
| you mean the... _pile of shame_?
| rudnevr wrote:
| doesn't your precious stash deserve an external folder or
| remote branch, in any case? the local repo is always a risk,
| so many things can ruin it. also, you only need to clean up
| like once a year, it's by definition a rare operation. A ton
| of branches doesn't grow overnight.
| freecodyx wrote:
| i once used ai to generate a command doing the exact same thing.
|
| git branch -vv | grep ': gone\\]' | awk '{print $1}' | xargs -n 1
| git branch -D
| spectaclepiece wrote:
| how is this a news item. LLMs figured this out for me two years
| ago
| kccqzy wrote:
| Why not just git dmb? https://manpages.debian.org/testing/git-
| delete-merged-branch...
| fragmede wrote:
| I want to point out explicitly that .git config supports aliases,
| so in .gitconfig put an [alias] section, and in that you can put
| ciaclean = "!alias ciaclean='git branch --merged origin/main |
| grep -vE "^\s _(*|main|develop) " | xargs -n 1 git branch -d'"
|
| so then it's `git ciaclean` and not bare `ciaclean` which imo is
| cleaner._
| atomicUpdate wrote:
| This is the same thing as `git rebase-update`, available in
| Chrome's `depot_tools`, which deletes merged branches.
|
| Beyond that, this is just OP learning how `xargs` works.
___________________________________________________________________
(page generated 2026-02-20 23:00 UTC)