diff --git a/share/completions/git.fish b/share/completions/git.fish index 45499348a..98ad430f6 100644 --- a/share/completions/git.fish +++ b/share/completions/git.fish @@ -65,6 +65,10 @@ function __fish_git_local_branches __fish_git for-each-ref --format='%(refname:strip=2)%09Local Branch' --sort=-committerdate refs/heads/ 2>/dev/null end +function __fish_git_remote_branches + __fish_git for-each-ref --format='%(refname:strip=2)%09Remote Branch' refs/remotes/ 2>/dev/null +end + function __fish_git_unique_remote_branches # `git checkout` accepts remote branches without the remote part # if they are unambiguous. @@ -90,6 +94,12 @@ function __fish_git_heads end end +function __fish_git_remote_heads + # Example of output parsed: + # "remote.upstream.url git@github.com:fish-shell/fish-shell.git" -> "upstream\tgit@github.com:fish-shell/fish-shell.git" + __fish_git for-each-ref --format="%(refname:strip=2)" 'refs/remotes/*/HEAD' | path dirname +end + function __fish_git_refs __fish_git_branches __fish_git_tags @@ -102,6 +112,24 @@ function __fish_git_remotes __fish_git config --get-regexp 'remote\.[a-z]+\.url' | string replace -rf 'remote\.(.*)\.url (.*)' '$1\t$2' end +set -g __fish_git_recent_commits_arg +set -g __fish_git_unqualified_unique_remote_branches false +set -g __fish_git_filter_non_pushable '' + +function __fish_git_add_revision_completion + set -l c complete -f -c git $argv -n 'not contains -- -- (commandline -xpc)' -ka + # The following dynamic, order-preserved (-k) completions will be shown in reverse order (see #9221) + $c "(__fish_git_recent_commits $__fish_git_recent_commits_arg $__fish_git_filter_non_pushable)" + $c "(__fish_git_tags)" -d Tag + $c "(__fish_git_remote_heads $__fish_git_filter_non_pushable)" -d 'Remote alias' + $c "(__fish_git_heads $__fish_git_filter_non_pushable)" -d Head + $c "(__fish_git_remote_branches $__fish_git_filter_non_pushable)" + if $__fish_git_unqualified_unique_remote_branches + $c "(__fish_git_unique_remote_branches $__fish_git_filter_non_pushable)" -d 'Unique Remote Branch' + end + $c "(__fish_git_local_branches)" -d 'Local Branch' +end + function __fish_git_files # A function to show various kinds of files git knows about, # by parsing `git status --porcelain`. @@ -1038,7 +1066,7 @@ complete -f -c git -n '__fish_git_using_command fetch' -l shallow-since -d 'Deep complete -f -c git -n '__fish_git_using_command fetch' -l shallow-exclude -d 'Deepen history of shallow clone, excluding rev' complete -f -c git -n '__fish_git_using_command fetch' -l unshallow -d 'Convert to a complete repository' complete -f -c git -n '__fish_git_using_command fetch' -l refetch -d 'Re-fetch without negotiating common commits' -complete -f -c git -n '__fish_git_using_command fetch' -l negotiation-tip -d 'Only report commits reachable from these tips' -kxa '(__fish_git_commits; __fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command fetch' -l negotiation-tip -d 'Only report commits reachable from these tips' -x complete -f -c git -n '__fish_git_using_command fetch' -l negotiate-only -d "Don't fetch, only show commits in common with the server" complete -f -c git -n '__fish_git_using_command fetch' -l filter -ra '(__fish_git_filters)' -d 'Request a subset of objects from server' @@ -1091,11 +1119,9 @@ complete -f -c git -n "__fish_git_using_command remote" -n "__fish_seen_subcomma ### show complete -f -c git -n __fish_git_needs_command -a show -d 'Show the last commit of a branch' -complete -f -c git -n '__fish_git_using_command show' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_branches)' -complete -f -c git -n '__fish_git_using_command show' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_tags)' -d Tag -complete -f -c git -n '__fish_git_using_command show' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_commits)' -complete -f -c git -n '__fish_git_using_command show' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_complete_stashes)' +__fish_git_add_revision_completion -n '__fish_git_using_command show' complete -f -c git -n __fish_git_needs_rev_files -n 'not contains -- -- (commandline -xpc)' -xa '(__fish_git_complete_rev_files)' +complete -f -c git -n '__fish_git_using_command show' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_complete_stashes)' complete -F -c git -n '__fish_git_using_command show' -n 'contains -- -- (commandline -xpc)' complete -f -c git -n '__fish_git_using_command show' -l format -d 'Pretty-print the contents of the commit logs in a given format' -a '(__fish_git_show_opt format)' complete -f -c git -n '__fish_git_using_command show' -l abbrev-commit -d 'Show only a partial hexadecimal commit object name' @@ -1183,13 +1209,12 @@ complete -c git -n '__fish_git_using_command am' -l show-current-patch -a 'diff ### checkout complete -F -c git -n '__fish_git_using_command checkout' -n 'contains -- -- (commandline -xpc)' complete -f -c git -n __fish_git_needs_command -a checkout -d 'Checkout and switch to a branch' +begin + set -lx __fish_git_recent_commits_arg --all + set -lx __fish_git_unqualified_unique_remote_branches true + __fish_git_add_revision_completion -n '__fish_git_using_command checkout' +end -# The following dynamic, order-preserved (-k) completions will be shown in reverse order (see #9221) -complete -f -c git -n '__fish_git_using_command checkout' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_recent_commits --all)' -complete -f -c git -n '__fish_git_using_command checkout' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_tags)' -d Tag -complete -f -c git -n '__fish_git_using_command checkout' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_heads)' -d Head -complete -f -c git -n '__fish_git_using_command checkout' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_unique_remote_branches)' -d 'Unique Remote Branch' -complete -f -c git -n '__fish_git_using_command checkout' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_branches)' # In the presence of changed files, `git checkout ...` assumes highest likelihood is intent to restore so this comes last (aka shown first). complete -f -c git -n '__fish_git_using_command checkout' -ka '(__fish_git_files modified deleted modified-staged-deleted)' @@ -1426,9 +1451,7 @@ complete -x -c git -n '__fish_git_using_command daemon' -l access-hook -d 'Hook ### describe complete -c git -n __fish_git_needs_command -a describe -d 'Give an object a human readable name' -complete -f -c git -n '__fish_git_using_command describe' -ka '(__fish_git_tags)' -d Tag -complete -f -c git -n '__fish_git_using_command describe' -ka '(__fish_git_branches)' -complete -f -c git -n '__fish_git_using_command describe' -ka '(__fish_git_heads)' -d Head +__fish_git_add_revision_completion -n '__fish_git_using_command describe' complete -f -c git -n '__fish_git_using_command describe' -l dirty -d 'Describe the state of the working tree, append dirty if there are local changes' complete -f -c git -n '__fish_git_using_command describe' -l broken -d 'Describe the state of the working tree, append -broken instead of erroring' complete -f -c git -n '__fish_git_using_command describe' -l all -d 'Use all tags, not just annotated' @@ -1448,7 +1471,10 @@ complete -f -c git -n '__fish_git_using_command describe' -l first-parent -d 'Fo complete -c git -n __fish_git_needs_command -a diff -d 'Show changes between commits and working tree' complete -c git -n '__fish_git_using_command diff' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_ranges)' complete -c git -n '__fish_git_using_command diff' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_complete_stashes)' -complete -c git -n '__fish_git_using_command diff' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_recent_commits --all)' +begin + set -lx __fish_git_recent_commits_arg --all + __fish_git_add_revision_completion -n '__fish_git_using_command diff' +end complete -c git -n '__fish_git_using_command diff' -l cached -d 'Show diff of changes in the index' complete -c git -n '__fish_git_using_command diff' -l staged -d 'Show diff of changes in the index' complete -c git -n '__fish_git_using_command diff' -l no-index -d 'Compare two paths on the filesystem' @@ -1779,7 +1805,7 @@ complete -f -c git -n '__fish_git_using_command maintenance' -l schedule -d 'Run ### merge complete -f -c git -n __fish_git_needs_command -a merge -d 'Join multiple development histories' -complete -f -c git -n '__fish_git_using_command merge' -ka '(__fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command merge' complete -f -c git -n '__fish_git_using_command merge' -l commit -d "Autocommit the merge" complete -f -c git -n '__fish_git_using_command merge' -l no-commit -d "Don't autocommit the merge" complete -f -c git -n '__fish_git_using_command merge' -s e -l edit -d 'Edit auto-generated merge message' @@ -1815,7 +1841,7 @@ complete -f -c git -n '__fish_git_using_command merge' -l no-autostash -d 'Do no ### merge-base complete -f -c git -n __fish_git_needs_command -a merge-base -d 'Find a common ancestor for a merge' -complete -f -c git -n '__fish_git_using_command merge-base' -ka '(__fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command merge-base' complete -f -c git -n '__fish_git_using_command merge-base' -s a -l all -d 'Output all merge bases for the commits, instead of just one' complete -f -c git -n '__fish_git_using_command merge-base' -l octopus -d 'Compute the best common ancestors of all supplied commits' complete -f -c git -n '__fish_git_using_command merge-base' -l independent -d 'Print a minimal subset of the supplied commits with the same ancestors' @@ -1933,9 +1959,10 @@ complete -f -c git -n '__fish_git_using_command range-diff' -l no-dual-color -d ### push complete -f -c git -n __fish_git_needs_command -a push -d 'Push changes elsewhere' complete -f -c git -n '__fish_git_using_command push' -n 'not __fish_git_branch_for_remote' -a '(__fish_git_remotes)' -d 'Remote alias' -complete -f -c git -n '__fish_git_using_command push' -n __fish_git_branch_for_remote -ka '(__fish_git_tags)' -d Tag -complete -f -c git -n '__fish_git_using_command push' -n __fish_git_branch_for_remote -ka '(__fish_git_branches)' -complete -f -c git -n '__fish_git_using_command push' -n __fish_git_branch_for_remote -ka '(__fish_git_heads)' +begin + set -lx __fish_git_filter_non_pushable '| string replace -r "(\t.*)?\$" ":\$1"' + __fish_git_add_revision_completion -n '__fish_git_using_command push' -n __fish_git_branch_for_remote +end # The "refspec" here is an optional "+" to signify a force-push complete -f -c git -n '__fish_git_using_command push' -n __fish_git_branch_for_remote -n 'string match -q "+*" -- (commandline -ct)' -ka '+(__fish_git_branches | string replace -r \t".*" "")' -d 'Force-push branch' # git push REMOTE :BRANCH deletes BRANCH on remote REMOTE @@ -1962,11 +1989,7 @@ complete -f -c git -n '__fish_git_using_command push' -l progress -d 'Force prog ### rebase complete -f -c git -n __fish_git_needs_command -a rebase -d 'Reapply commit sequence on a new base' -complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_remotes)' -d 'Remote alias' -complete -f -c git -n '__fish_git_using_command rebase' -ka '(__fish_git_branches)' -complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_heads)' -d Head -complete -f -c git -n '__fish_git_using_command rebase' -ka '(__fish_git_tags)' -d Tag -k -complete -f -c git -n '__fish_git_using_command rebase' -a '(__fish_git_recent_commits)' -k +__fish_git_add_revision_completion -n '__fish_git_using_command rebase' complete -f -c git -n '__fish_git_using_command rebase' -n __fish_git_is_rebasing -l continue -d 'Restart the rebasing process' complete -f -c git -n '__fish_git_using_command rebase' -n __fish_git_is_rebasing -l abort -d 'Abort the rebase operation' complete -f -c git -n '__fish_git_using_command rebase' -n __fish_git_is_rebasing -l edit-todo -d 'Edit the todo list' @@ -1991,7 +2014,7 @@ complete -f -c git -n '__fish_git_using_command rebase' -l no-autosquash -d 'No complete -f -c git -n '__fish_git_using_command rebase' -l autostash -d 'Before starting rebase, stash local changes, and apply stash when done' complete -f -c git -n '__fish_git_using_command rebase' -l no-autostash -d 'Do not stash local changes before starting rebase' complete -f -c git -n '__fish_git_using_command rebase' -l no-ff -d 'No fast-forward' -complete -f -c git -n '__fish_git_using_command rebase' -l onto -d 'Rebase current branch onto given upstream or newbase' -rka '(__fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command rebase' -l onto -d 'Rebase current branch onto given upstream or newbase' -r complete -f -c git -n '__fish_git_using_command rebase' -l update-refs -d 'Update any branches that point to commits being rebased' complete -f -c git -n '__fish_git_using_command rebase' -l no-update-refs -d 'Don\'t update any branches that point to commits being rebased' # This actually takes script for $SHELL, but completing that is... complicated. @@ -2010,7 +2033,7 @@ complete -c git -n __fish_git_needs_command -a reset -d 'Reset current HEAD to t complete -f -c git -n '__fish_git_using_command reset' -l hard -d 'Reset the index and the working tree' complete -f -c git -n '__fish_git_using_command reset' -l soft -d 'Reset head without touching the index or the working tree' complete -f -c git -n '__fish_git_using_command reset' -l mixed -d 'The default: reset the index but not the working tree' -complete -c git -n '__fish_git_using_command reset' -n 'not contains -- -- (commandline -xpc)' -ka '(__fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command reset' # reset can either undo changes to versioned modified files, # or remove files from the staging area. # Deleted files seem to need a "--" separator. @@ -2042,7 +2065,10 @@ complete -f -c git -n '__fish_git_using_command switch' -ka '(__fish_git_unique_ complete -f -c git -n '__fish_git_using_command switch' -ka '(__fish_git_branches)' complete -f -c git -n '__fish_git_using_command switch' -s c -l create -d 'Create a new branch' complete -f -c git -n '__fish_git_using_command switch' -s C -l force-create -d 'Force create a new branch' -complete -f -c git -n '__fish_git_using_command switch' -s d -l detach -rka '(__fish_git_recent_commits --all)' +begin + set -lx __fish_git_recent_commits_arg --all + __fish_git_add_revision_completion -n '__fish_git_using_command switch' -s d -l detach -r +end complete -f -c git -n '__fish_git_using_command switch' -s d -l detach -d 'Switch to a commit for inspection and discardable experiment' -rka '(__fish_git_refs)' complete -f -c git -n '__fish_git_using_command switch' -l guess -d 'Guess branch name from remote branch (default)' complete -f -c git -n '__fish_git_using_command switch' -l no-guess -d 'Do not guess branch name from remote branch' @@ -2067,9 +2093,7 @@ complete -f -c git -n __fish_git_needs_command -a rev-list -d 'List commits in c ### rev-parse complete -f -c git -n __fish_git_needs_command -a rev-parse -d 'Parse revision names or give repo information' -complete -f -c git -n '__fish_git_using_command rev-parse' -ka '(__fish_git_branches)' -complete -f -c git -n '__fish_git_using_command rev-parse' -a '(__fish_git_heads)' -d Head -complete -c git -n '__fish_git_using_command rev-parse' -ka '(__fish_git_tags)' -d Tag +__fish_git_add_revision_completion -n '__fish_git_using_command rev-parse' complete -c git -n '__fish_git_using_command rev-parse' -l abbrev-ref -d 'Output non-ambiguous short object names' ### revert @@ -2119,7 +2143,7 @@ complete -f -c git -n '__fish_git_using_command stripspace' -s c -l comment-line ### tag complete -f -c git -n __fish_git_needs_command -a tag -d 'Create, list, delete or verify a tag object signed with GPG' -complete -f -c git -n '__fish_git_using_command tag' -n '__fish_not_contain_opt -s d' -n '__fish_not_contain_opt -s v' -n 'test (count (commandline -xpc | string match -r -v \'^-\')) -eq 3' -ka '(__fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command tag' -n '__fish_not_contain_opt -s d' -n '__fish_not_contain_opt -s v' -n 'test (count (commandline -xpc | string match -r -v \'^-\')) -eq 3' complete -f -c git -n '__fish_git_using_command tag' -s a -l annotate -d 'Make an unsigned, annotated tag object' complete -f -c git -n '__fish_git_using_command tag' -s s -l sign -d 'Make a GPG-signed tag' complete -f -c git -n '__fish_git_using_command tag' -s d -l delete -d 'Remove a tag' @@ -2180,11 +2204,10 @@ complete -f -c git -n "__fish_git_using_command worktree" -n "not __fish_seen_su complete -f -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add move remove' -s f -l force -d 'Override safeguards' complete -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -complete -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -ka '(__fish_git_branches)' -complete -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -ka '(__fish_git_heads)' -d Head -complete -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -ka '(__fish_git_tags)' -d Tag -complete -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -ka '(__fish_git_unique_remote_branches)' -d 'Unique Remote Branch' -complete -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -ka '(__fish_git_local_branches)' +begin + set -lx __fish_git_unqualified_unique_remote_branches true + __fish_git_add_revision_completion -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' +end complete -x -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -s b -d 'Create a new branch' complete -x -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -s B -d 'Create a new branch even if it already exists' complete -f -c git -n '__fish_git_using_command worktree' -n '__fish_seen_subcommand_from add' -l detach -d 'Detach HEAD in the new working tree' @@ -2241,7 +2264,7 @@ complete -f -c git -n __fish_git_needs_command -a config -d 'Set and read git co ### format-patch complete -f -c git -n __fish_git_needs_command -a format-patch -d 'Generate patch series to send upstream' -complete -f -c git -n '__fish_git_using_command format-patch' -ka '(__fish_git_branches)' +__fish_git_add_revision_completion -n '__fish_git_using_command format-patch' complete -c git -n '__fish_git_using_command format-patch' -s o -l output-directory -xa '(__fish_complete_directories)' complete -f -c git -n '__fish_git_using_command format-patch' -s p -l no-stat -d "Generate plain patches without diffstat" complete -f -c git -n '__fish_git_using_command format-patch' -s s -l no-patch -d "Suppress diff output" @@ -2603,3 +2626,8 @@ for file in (path filter -xZ $PATH/git-* | path basename) complete -c git -f -n "__fish_git_using_command $cmd" -a "(__fish_git_complete_custom_command $cmd)" set -a __fish_git_custom_commands_completion $file end + +functions --erase __fish_git_add_revision_completion +set -eg __fish_git_recent_commits_arg +set -eg __fish_git_unqualified_unique_remote_branches +set -eg __fish_git_filter_non_pushable