Back

I found a useful Git one liner buried in leaked CIA developer docs

446 points6 hoursspencer.wtf
fphilipe3 hours ago

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

rubinlinux55 minutes ago

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.
WickyNilliams4 hours ago

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...
lloeki4 hours ago

> 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
WickyNilliams4 hours ago

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 :)

MathiasPius4 hours ago

You can pull another branch without switching first:

  git switch my-test-branch
  ...
  git pull origin main:main
  git rebase main
hiccuphippo3 hours ago

You can also rebase directly on the remote branch

    git fetch
    git rebase origin/main
WickyNilliams3 hours ago

Nice. That'll make things a bit smoother. Changing branches often trips me up when I would later `git switch -`.

mroche3 hours ago

Likewise with the other way around, just switch pull with push.

huntervang3 hours ago

I have always done `git pull origin main -r`

lloeki5 hours ago

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_g5 hours ago

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.

otsaloma1 hour ago

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...

laksdjf3 hours ago

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

arccy2 hours ago

if you're using gerrit then you have the Change-Id trailer you can match against?

de46le2 hours ago

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 :)

WorldMaker4 hours ago

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.

masklinn5 hours ago

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.

samhclark4 hours ago

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.
bobjordan3 hours ago

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.

joshuamcginnis3 hours ago

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.

ear7h2 hours ago

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/...

defen1 hour ago

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.

themafia1 hour ago

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.

imdsm3 hours ago

I'll change my default branches to main when Masterclass change their name to Mainclass

ffsm83 hours ago

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

r14c3 hours ago

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.

kridsdale13 hours ago

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.

yokoprime2 hours ago

This is why diffs / LoC is a terrible metric. It shows nothing other than a willingness to push large changesets upstream.

jihadjihad3 hours ago

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.

8organicbits2 hours ago

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.

reenorap1 hour ago

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.

layer82 hours ago

> What color is ink on a page?

Middle gray, according to modern UX designers. ;)

pmontra1 hour ago

You are lucky. It's often light gray on thin fonts.

pbhjpbhj2 hours ago

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.

tucnak3 hours ago

They measure LoC contributions at FB?

doetoe1 hour ago

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

yokoprime2 hours ago

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.

tom_2 hours ago

Thank you for creating the containment thread.

botusaurus1 hour ago

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"?

drcongo1 hour ago

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.

TacticalCoder3 hours ago

> 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.

As a white person from slavic origins (my mother had an Ukrainian name and we're originally from the ukrainian city of Kyiv), my ancestors were OG slaves. It's literally where the word "slave" comes from: same etymology. We, white people, have been traded as slaves by many (including other whites) since times immemorial.

And yet I really literally don't care if people name their main branch "master" or "main". I like "trunk" but I'm sure some people with a political agenda could find a way to explain how "truck" is offensive.

You have my blessings and I hope the blessings from many people with slavic origins.

maest2 hours ago

The whole master/main thing is a dinstinctly American culture war issue which, unfortunately, infected the rest of the world.

hungryhobbit2 hours ago

> 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) ...

stevekemp2 hours ago

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.

gritzko4 hours ago

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

whazor6 hours ago

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.

rw_panic0_05 hours ago

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"?

freedomben4 hours ago

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.

whazor3 hours ago

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'.

zenoprax2 hours ago

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.

embedding-shape4 hours ago

> 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.

kaoD3 hours ago

> 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.

+1
embedding-shape3 hours ago
sclangdon5 hours ago

Isn't it this case no matter who wrote the code? How do you ever run anything if you're worried about bugs?

phailhaus5 hours ago

When I write the code myself, I'm not worried that I snuck a `git reset --hard` somewhere.

hennell4 hours ago

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)

layer82 hours ago

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.

ithkuil4 hours ago

I assume that whatever I type can be also flawed and take precautions like backups etc

eulers_secret5 hours ago

Tig is a nice and long-maintained git tui you might enjoy, then!

If nothing else maybe for inspiration

kqr4 hours ago

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

firesteelrain5 hours ago

Can you explain TUI? I have never heard this before

Bjartr5 hours ago

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.

Muvasa5 hours ago

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)

kstrauser3 hours ago

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.

irl_zebra4 hours ago

"It's not about saving time, it's about eliminating the mental toll from having to context switch"

This broke my brain! Woah!

criddell5 hours ago

> 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.

GCUMstlyHarmls5 hours ago

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.

giglamesh5 hours ago

So the acronym is for Terrible User Interface? ;)

worksonmine4 hours ago

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.

allarm5 hours ago

No it's not.

ses19845 hours ago

Terminal UI.

booleandilemma5 hours ago

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.

freedomben4 hours ago

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.

0x1ch3 hours ago

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.

snozolli4 hours ago

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

KPGv25 hours ago

it's the name gen Z and gen alpha puppyn00bs have given to what us old heads have always called CLIs

on tik too young folks are always discovering "revolutionary" things and giving them names, ignoring they're either super mundane, or already have a name

on one hand, i absolutely LOVE the passion for discovery and invention

on the other hand, if you're 19yo you probably didn't discover something revolutionary

(Edit: I've seen some people online suggest a CLI is only when you manually type the command yourself, while a TUI incorporates text-based graphical elements, but that's something invented by young people; everything before GUIs was called a CLI until pretty recently. A terminal is /literally/ a command-line interface.)

TarqDirtyToMe5 hours ago

They aren’t the same thing. TUI refers to interactive ncurses-like interfaces. Vim has a TUI, ls does not

I’m fairly certain this terminology has been around since at least the early aughts.

cristoperb5 hours ago

I don't know when the term became widespread for gui-style terminal programs, but the wikipedia entry has existed for more than 20 years so I think it is an older term than you imply.

https://en.wikipedia.org/w/index.php?title=Text-based_user_i...

philiplu5 hours ago

Sorry, but this 65 yo grey-beard disagrees. A TUI to me, back in the 80s/90s, was something that ran in the terminal and was almost always ncurses-based. This was back when I was still using ADM-3A serial terminals, none of that new-fangled PCs stuff.

bombcar4 hours ago

Exactly. A CLI is a single line - like edlin. A TUI takes over all or most of the screen, like edit or vi or emacs.

Norton Commander (or Midnight Commander) is probably the quintessential example of a powerful TUI; it can do things that would be quite hard to replicate as easily in a CLI.

+2
KPGv24 hours ago
john_strinlai4 hours ago

[dead]

Trufa5 hours ago

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.

whazor3 hours ago

This is how I solve the dependencies with Nix: https://gist.github.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.

unshavedyak4 hours ago

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.

SauntSolaire4 hours ago

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.

freedomben4 hours ago

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.

NetOpWibby4 hours ago

To save time and energy?

elliotbnvl5 hours ago

The deps question is huge, let me know if you solve it.

CalebJohn4 hours ago

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

hattmall5 hours ago

What are some examples of useful TUI you made? I'm generally opposed to the concept

lionkor5 hours ago

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

htnthrow112205 hours ago

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.

MarsIronPI5 hours ago

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.

bmacho5 hours ago

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.

duneisagoodbook5 hours ago

yeah! they should focus on more productive pursuits, like telling people online what to do with their time and resources.

morissette5 hours ago

And these are things outside of our control.

jo-m5 hours ago

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...
arusahni5 hours ago

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

parliament326 hours ago

So effectively "I just discovered xargs"? Not to disparage OP but there isn't anything particularly novel here.

Someone12345 hours ago

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?

parliament324 hours ago

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.

superxpro124 hours ago

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.

jimmydoe5 hours ago

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

vntok5 hours ago

Where else would you learn about triple-entry bookkeeping?

ggrab2 hours ago

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)

skydhash5 hours ago

People really do need to read the “Unix Power Tools” book and realize their problem has been solved for decades.

gosub1005 hours ago

"People just need to find the info they don't know about, so then they'll know it."

gavinray3 hours ago

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

SoftTalker3 hours ago

People need to be curious. Then they seek out the info they don't know about.

cgfjtynzdrfht5 hours ago

[dead]

tonmoy1 hour ago

I’m surprised to see not enough people using xargs, or maybe I overuse it

andrewaylett2 hours ago

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 :).

Cherub07745 hours ago

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'
masklinn5 hours ago

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'
maerF0x04 hours ago

    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
gritzko5 hours ago

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...

oniony5 hours ago

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.

gritzko5 hours ago

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.

EricRiese4 hours ago

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.

coderpersson4 hours ago

`git trash`

https://github.com/henrikpersson/git-trash

I use this script with a quick overview to prevent accidentally deleting something important

nikeee4 hours ago

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.

d0liver5 hours ago

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.

WorldMaker4 hours ago

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.
jimnotgym4 hours ago

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.

1a527dd55 hours ago

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.
sigio6 hours ago

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
microflash3 hours ago

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

bobabob3 hours ago

Using grep and xargs is worth a whole blog post now? hmmmmm

jldugger3 hours ago

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
taude5 hours ago

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'
samtrack20192 hours ago

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

devy3 hours ago

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."

SoftTalker3 hours ago

It's hardly a profound insight. If you're fluent at the command line, xargs enables all sorts of conveniences.

stabbles5 hours ago

Missed opportunity to call it `git ciao`

dewey6 hours ago

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...

password43215 hours ago

I don't delete branches, I just work with the top several most recently modified.

the_real_cher5 hours ago

How to list those? Is there a flag for git branch to sort by recently modified?

(not on my computer right now to check)

rpozarickij4 hours ago

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

embedding-shape4 hours ago

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.

mrbonner4 hours ago

> 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 :-)

jen204 hours ago

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.

trashymctrash5 hours ago

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
lkbm3 hours ago

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.

ihsoy5 hours ago

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

nightpool5 hours ago

`--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-shape4 hours ago

> 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.

plqbfbv5 hours ago

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.

cowlby4 hours ago

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.

mywittyname4 hours ago

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.

block_dagger4 hours ago

I cleanup branches interactively with a few lines of bash, which takes a bit more time but is less likely to destroy active work.

micw5 hours ago

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.

markus_zhang4 hours ago

Oh this is what ChatGPT told me when I asked "How to remove all local branch except main"...

arduanika1 hour ago

Trust Langley to neatly tie up all the loose ends.

dietr1ch5 hours ago

Wait, why would the update for the silly master->main change be swapping the excluded regex instead of just excluding both?

PunchyHamster5 hours ago

coz OP has agenda and

> Since most projects now use main instead of master

some delusions to boot

Sesse__5 hours ago

You probably want git-dmb (dmb = delete merged branches) for a safe and more comprehensive way of dealing with this.

puzz5 hours ago

Or git-old-branches/git-recent from git-plus

https://github.com/tkrajina/git-plus

Disclaimer, I'm the author ^^

galbar6 hours ago

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

blakesterz5 hours ago

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.

gjvc5 hours ago

"trapd00r" is the theme you want, if only because the name is cool

giglamesh5 hours ago

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!

Arch-TK5 hours ago

Unfortunately doesn't work if the project you work on squashes everything :(

schiffern5 hours ago

"ciaclean" is a nice touch.

I assume CIA stands for Clean It All.

sammyteee5 hours ago

"Clean It All, Clean" :P

plufz5 hours ago

I assume it means mess up commit history and install ”our” BDFL.

Svoka2 hours ago

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
rickknowlton4 hours ago

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??
devhouse4 hours ago

don't forget to fetch first

nivcmo48 minutes ago

[dead]

bgfjhgghhhg4 hours ago

[dead]

morissette5 hours ago

[flagged]

sidsud5 hours ago

agree, this just seems click-baity. if you're familiar with the UNIX Way, this is a one-liner you'd naturally write. CIA leaked docs mention and a blog post for this?

djmips4 hours ago

the Clandestine allure for clicks for sure but you know what - the comments have been pretty interesting.