It also has one for squash-merged branches: gbds
Very useful I've been using them for years
That says so much about the generation we are in, just don’t go to school but learn math from mafia
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?
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.
#!/bin/sh
git branch --merged | egrep -v "(^\*|master|main|dev)" | xargs --no-run-if-empty
git branch -d #!/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. 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 exist2. 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
https://replicated.wiki/blog/partII.html#navigating-the-hist...
Still, many oddities of git are inevitable due to its underlying storage model, so it makes sense to explore other models too.
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... [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 statsWhat 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.
> 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.
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.
# ~/.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.I assume CIA stands for Clean It All.
git fetch --prune && git branch -vv | awk '/: gone]/{print $1}' | xargs git branch -D git branch --merged | grep -v "\*\|master" | xargs -n 1 git branch -d
Why don't we all use a shell with lists and objects? That one line above could look like this git.branches()
.filter(b => b.merged && !b.current && b.name !== "master" && b.name !== "main")
.forEach(b => git.deleteBranch(b.name)) 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'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' '!f() { git branch --format '%(refname:short) %(upstream:track,nobracket)' | awk '$2~/^gone$/{print $1}' | xargs git branch -D; }; f'> Since most projects now use main instead of master
some delusions to boot
https://github.com/tkrajina/git-plus
Disclaimer, I'm the author ^^
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
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.
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.
(not on my computer right now to check)
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.
I have replaced my standard ddg of, "git <the thing i need>" with asking Claude to give me the commands I need to run.
# 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...https://github.com/foriequal0/git-trim
Readme also explains why it's better than a bash-oneliner in some cases.
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. 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
whazor•1h ago
lionkor•1h ago
MarsIronPI•1h ago
duneisagoodbook•1h ago
morissette•1h ago
htnthrow11220•1h ago
bmacho•1h ago
Maybe I'll try using small TUI too.
Trufa•1h ago
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•1h ago
SauntSolaire•38m ago
freedomben•15m ago
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•11m ago
unshavedyak•34m ago
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.
firesteelrain•1h ago
ses1984•1h ago
Bjartr•1h ago
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•1h ago
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•40m ago
This broke my brain! Woah!
criddell•50m ago
Or mouse / trackpad.
I really haven't seen anything better for making TUIs than Borland's Turbo Vision framework from 35ish years ago.
GCUMstlyHarmls•1h ago
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•1h ago
allarm•1h ago
KPGv2•1h ago
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.)
TarqDirtyToMe•1h ago
I’m fairly certain this terminology has been around since at least the early aughts.
philiplu•59m ago
KPGv2•41m ago
https://books.google.com/ngrams/graph?content=TUI&year_start...
Basically it was never used, then it was heavily used, and then never used, and then in the early 00s it took off again.
That'd explain why you used it, I never did, and now young kids are.
marssaxman•16m ago
It's not a term I recall hearing at all when I started using computers in the mid-'80s - all that mattered back then was "shiny new GUI, or the clunky old thing?" I really thought it was a retroneologism when I first heard it, maybe twenty years ago.
bombcar•38m ago
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.
cristoperb•52m ago
https://en.wikipedia.org/w/index.php?title=Text-based_user_i...
booleandilemma•1h ago
freedomben•20m ago
hattmall•1h ago
rw_panic0_0•1h ago
sclangdon•1h ago
phailhaus•59m ago
embedding-shape•33m ago
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.
freedomben•26m ago
ithkuil•6m ago
eulers_secret•1h ago
If nothing else maybe for inspiration
kqr•25m ago
I have a draft here about one aspect of Magit I enjoy: https://entropicthoughts.com/rebasing-in-magit