Last active
September 24, 2025 10:02
-
-
Save zzhuolun/163536756479ecbdb7ae09620cfcdd5e to your computer and use it in GitHub Desktop.
Fish shell functions for batched git operations
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 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