" The purpose of creating this autoload is with functions like git_branch_log " which opens another 'git' filetype buffer defining such a function in " after/ftplugin/ft.vim results in a complain about duplicated function since " anything defined there will be loaded again. See :help autoload. " Delete the branch on the current line in the output of Git branch -a. function! git#git_branch_delete() abort let line = trim(getline('.')) let branch = split(line, "/") if len(branch) == 1 " Handles the case for local branch execute "Git branch -D " . branch[0] else " Handles the case for remote remotes/remote_name/branch_name let remote = branch[1] let branch = branch[2] execute "Git push -d " . remote . " " . branch execute "Git branch -D " . branch endif silent execute "bw" endfunction " Checkout the branch on the current line in the output of Git branch -a. function! git#git_branch_checkout() abort let line = trim(getline('.')) let branch = split(line, "/") if len(branch) == 1 " Handles the case for local branch silent execute "Git checkout " . branch[0] else " Handles the case for remote remotes/remote_name/branch_name let remote = join(branch[1:2], "/") silent execute "Git checkout " . remote silent execute "Git checkout -b " . branch[2] endif silent execute "bw" endfunction " Get the log of the branch on current line in the output of Git branch -a. function! git#git_branch_log() abort let line = trim(getline('.')) let branch = split(line, "/") " Close the buffer opened by Git branch -a silent execute "bw" if len(branch) == 1 " Handles the case for local branch execute "Git log " . branch[0] else " Handles the case for remote remotes/remote_name/branch_name let remote = join(branch[1:2], "/") execute "Git log " . remote endif endfunction " Get the log of the branch on current line in the output of Git branch -a. " This one returns a log where a line has the form . This " acts as a precursor to what we run cherry-pick on. function! git#git_branch_log_pretty() abort let line = trim(getline('.')) let branch = split(line, "/") " Close the buffer opened by Git branch -a silent execute "bw" if len(branch) == 1 " Handles the case for local branch execute "Git log --pretty=oneline --no-merges " . branch[0] else " Handles the case for remote remotes/remote_name/branch_name let remote = join(branch[1:2], "/") execute "Git log --pretty=oneline --no-merges " . remote endif endfunction " Run Git cherry-pick on the commit in the line which we are at. To be used " after running some variation of Git log. function! git#git_cherry_pick() abort " A line in Git log is of the form commit let line = trim(getline('.')) let commit = split(line, " ") silent execute "Git cherry-pick " . commit[1] endfunction " Git cherry-pick a range of commits. To be run on output of Git log " --pretty=oneline. See git_branch_log_pretty. function! git#git_cherry_pick_range() abort let [lnum1, col1] = getpos("'<")[1:2] let [lnum2, col2] = getpos("'>")[1:2] let lines = reverse(getline(lnum1, lnum2)) if len(lines) == 0 return '' endif let oldCommit = split(lines[0], " ")[:0][0] let newCommit = split(lines[-1], " ")[:0][0] execute "Git cherry-pick " . oldCommit . "^.." . newCommit silent execute "bw" endfunction " Run Git difftool on the commit in the line which we are at. To be used after " running some variation of Git log. function! git#git_diff_commit() abort " A line in Git log is of the form commit let line = trim(getline('.')) let commit = split(line, " ") silent execute "Git difftool -y " . commit[1] . "^!" endfunction " Run DiffviewOpen on the commit in the line which we are at. To be used after " running some variation of Git log. function! git#git_diffview_commit() abort " A line in Git log is of the form commit let line = trim(getline('.')) let commit = split(line, " ") silent execute "DiffviewOpen " . commit[1] . "^!" endfunction " The next two functions allow scoping diffs by line range of a file and named " block in a file. Inspired by reading the following article. " https://susanpotter.net/software/tracking-diffs-by-scoping-to-file-range-function-method-or-class-changes-in-git/ " Use these two links as reference to come up with this function " https://vi.stackexchange.com/questions/17606/vmap-and-visual-block-how-do-i-write-a-function-to-operate-once-for-the-entire " https://stackoverflow.com/questions/41238238/how-to-map-vim-visual-mode-to-replace-my-selected-text-parts function! git#git_log_range() abort let [lnum1, col1] = getpos("'<")[1:2] let [lnum2, col2] = getpos("'>")[1:2] silent execute "Git log --no-patch -L " . lnum1 . "," . lnum2 . ":%" endfunction " Taken from https://learnvimscriptthehardway.stevelosh.com/chapters/33.html. " Modified and stripped to do what I needed. function! git#git_log_named_block() abort normal! `y silent execute "Git log --no-patch -L :" . trim(shellescape(@@)) . ":%" endfunction " Compares current branch against master. For eg. git log master..current. " This combined with Git difftool -y are helpful for MR reviews. function! git#git_log_compare() abort let default = split(trim(system('git symbolic-ref refs/remotes/origin/HEAD')), '/') let current = trim(system('git branch --show-current')) let are_we_on_default = match(default[3], current) if (are_we_on_default == 0) echom "We are already on default branch. Nothing to compare." else silent execute "Git log " . default[3] . ".." . current endif endfunction " Merge remote origin:master/main into local:master/main function! git#git_fetch_origin_merge() abort let default = split(trim(system('git symbolic-ref refs/remotes/origin/HEAD')), '/') execute "Git fetch origin " . default[3] . ":" . default[3] endfunction " Figures out whether default branch is main or master and runs git merge. function! git#git_merge_origin() abort let default = split(trim(system('git symbolic-ref refs/remotes/origin/HEAD')), '/') let current = trim(system("git branch --show-current")) let are_we_on_default = match(default[3], current) if (are_we_on_default == 0) echom "Merging origin/" . default[3] execute "Git merge origin/" . default[3] else echom "Not on " . default[3] endif endfunction " Rebase the current checked out branch to the branch on the current line. " Git branch -a should be run before this. function! git#git_rebase_branch() abort let line = trim(getline('.')) let branch = split(line, "/") if len(branch) == 1 " Handles the case for local branch execute "Git rebase " . branch[0] else " Handles the case for remote remotes/remote_name/branch_name let remote = branch[1] let branch = branch[2] execute "Git rebase " . remote . "/" . branch endif silent execute "bw" endfunction " Git reflog should be run first before invoking this function! git#git_reflog_restore() abort let line = trim(getline('.')) " A line in git reflog is of the form below " f6a8c7ed4 HEAD@{73}: rebase (pick): gst-rtmp: Add mux queues to stats gathering let sl1 = split(line, ":") " sl1[0] will give f6a8c7ed4 HEAD@{73} for above example let sl2 = split(sl1[0], " ") " sl2[0] will have f6a8c7ed4 and sl2[1] will have HEAD@{73} echom "Command executed will be: Git reset --hard " . sl2[1] call inputsave() let restore = input('Restore to: ' . line . '. Enter y to proceed: ') call inputrestore() let to_restore = match(restore, 'y') if (to_restore == 0) execute "Git reset --hard " . sl2[1] else echom "Not restoring to " . line endif endfunction " Figures out whether default branch is main or master and runs git rebase. function! git#git_rebase_origin() abort let default = split(trim(system('git symbolic-ref refs/remotes/origin/HEAD')), '/') echom "Rebasing current branch on origin/" . default[3] execute "Git rebase origin/" . default[3] endfunction