Created
December 2, 2021 15:25
-
-
Save jeremyf/b22f02d14ca06f213ce07ee8a3532da0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby -w | |
############################################################## | |
# | |
# Begin Commentary | |
# | |
############################################################## | |
# | |
# First, if you want to use this, I recommend you change the | |
# the file mode to executable: | |
# | |
# `chmod +x local-branches-with-missing-remote` | |
# | |
# This command writes to STDOUT a list of local branches that | |
# have upstream tracking branches, but who's upstream branches | |
# are now gone. | |
# | |
# Fair warning, this perhaps follows some of my internalized | |
# assumptions about repository setup. | |
# | |
# I would love if there already existed a function that does | |
# this, but part of why I write code is to also practice | |
# algorithms and critical thinking. | |
# | |
# Example to list local branches with missing remotes: | |
# | |
# $ cd ~/git/forem ; local-branches-with-missing-remote | |
# | |
# Example to delete local branches with missing remotes: | |
# | |
# $ local-branches-with-missing-remote | xargs git remote -D | |
# | |
# | |
############################################################## | |
# | |
# Begin Function | |
# | |
############################################################## | |
# | |
# Prune the remote branches that are gone. Also, don't worry | |
# about the output | |
`git remote update origin --prune >/dev/null 2>&1` | |
# The remote branch lines are of the form: | |
# | |
# - space | |
# - origin/branch-name | |
# | |
# Note: by convention, origin is the upstream I'm concerned | |
# about | |
remote_branches = `git branch --remotes` | |
.split("\n") | |
.map(&:strip) | |
# The verbose branch lines are of the form: | |
# | |
# - Branch Name | |
# - many spaces | |
# - SHA of latest commit | |
# - space | |
# - OPTIONAL: "[Remote Name]" | |
# - space | |
# - Subject of latest commit | |
local_verbose_branches = `git branch -vv` | |
.split("\n") | |
.map { |b| b.gsub(/^\*? +/, '').strip } | |
local_verbose_branches.each do |verbose_branch| | |
# Definitely don't want to delete this local branch. | |
next if verbose_branch.start_with?("main") | |
# Though I no longer use "master" for my projects, there are | |
# some outliers that do. | |
next if verbose_branch.start_with?("master") | |
# I might have a local branch that doesn't have a remote | |
# tracking branch. Skip those | |
next unless verbose_branch.include?("[origin") | |
branch_name = verbose_branch.split(/ +/)[0] | |
# Test if local branch has a remote branch | |
next if remote_branches.detect do |rb| | |
rb.include?(branch_name) | |
end | |
# Output the branch name for a local branch with what | |
# appears to be a removed upstream branch (e.g., the | |
# upstream branch was likely merged and deleted) | |
puts branch_name | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment