Skip to content

Instantly share code, notes, and snippets.

@zzhuolun
Last active September 24, 2025 10:02
Show Gist options
  • Select an option

  • Save zzhuolun/163536756479ecbdb7ae09620cfcdd5e to your computer and use it in GitHub Desktop.

Select an option

Save zzhuolun/163536756479ecbdb7ae09620cfcdd5e to your computer and use it in GitHub Desktop.
Fish shell functions for batched git operations
#!/usr/bin/env fish
#########################################################################
# Based on the bash script in https://github.com/jackokaiser/dot_profiles
#########################################################################
function find_git_repos
set ignore_pattern "(3|(t|T)hi)rd_?(p|P)arty"
if test (count $argv) -gt 0
if test $argv[1] = "-a"
set ignore_pattern "*"
end
end
# Note: Using command substitution syntax for fish
for repo in (find -L . -name ".git" -type d | sed 's/\/.git//' | grep -v "$ignore_pattern" | sort)
echo $repo | sed 's/^\.\///'
end
end
# forgit can handle most of your batch git requests. Just use it like plain git
function forgit
for repo in (find_git_repos)
echo "========= $repo ========="
git -C $repo $argv
end
end
# Same as forgit but includes third party directories
function forgit_all
for repo in (find_git_repos -a)
echo "========= $repo ========="
git -C $repo $argv
end
end
# Set upstream for all subfolders respecting current branches
function batch_git_set_upstream
# $argv[1] is remote_name
set repos (find_git_repos)
for repo in $repos
cd $repo
echo "----$repo----"
set branch (git status | head -n 1 | string split ' ')[3]
echo "Branch: $branch"
set list (git remote -v | cut -f 1 | sort -u)
if string match -q -- "*$argv[1]*" "$list"
echo "Setting upstream to $argv[1]"
git branch --set-upstream-to=$argv[1]/$branch
else
echo "Remote $argv[1] does not exist. Skipping repository"
end
cd -
end
end
# Create bare repository containing all repos from subfolders
function batch_git_create_bare_remote
# $argv[1] is remote_name
# $argv[2] is remote_url
set current_dir (pwd)
set repos (find_git_repos)
for repo in $repos
cd $repo
set local_repo (pwd)
echo "----$repo-----"
set bare_repo "$argv[2]/$repo"
mkdir -p $bare_repo
cd $bare_repo
git init --bare
cd $local_repo
git remote add $argv[1] $bare_repo
set branch (git status | head -n 1 | string split ' ')[3]
git push $argv[1] $branch
echo "Pushed branch: $branch to bare repository $argv[1]"
cd $current_dir
end
end
# Change remote URL for all repositories in subfolders
function batch_git_set_remote_url
# $argv[1] is remote_name
# $argv[2] is remote_base_url
set repos (find_git_repos)
for repo in $repos
cd $repo
set local_repo (pwd)
echo "----$repo-----"
set bare_repo "$argv[2]/$repo"
git remote set-url $argv[1] $bare_repo
set branch (git status | head -n 1 | string split ' ')[3]
cd -
end
end
# Add new remote to all git repos in subfolders
function batch_git_add_remote
# $argv[1] is remote_name
# $argv[2] is remote_base_url
set repos (find_git_repos)
for repo in $repos
cd $repo
set local_repo (pwd)
echo "----$repo-----"
set bare_repo "$argv[2]/$repo"
git remote add $argv[1] $bare_repo
set branch (git status | head -n 1 | string split ' ')[3]
cd -
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment