diff --git a/git-recent b/git-recent index 68ba7f7..33f3d57 100755 --- a/git-recent +++ b/git-recent @@ -1,62 +1,52 @@ #!/bin/bash -## -## git-recent -## -## list all local branches, sorted by last commit, formatted reall purdy -## +# +# git recent 2.0 - switching branches, but so fancy +# +# - view recently edited local branches +# - see unique commits to that branch, and optionally the branch diff (against the main/master/primary branch) with Ctrl-o +# - hit Enter to checkout the selected branch. +# - text filtering against branch names, too. +# -# Windows needs more basic format (#8, git-for-windows/git#865) -case $(uname -s) in - CYGWIN*|MINGW*|MSYS*) - branch='%(refname:short)' - ;; - *) - branch='%(color:yellow)%(refname:short)%(color:reset)' - ;; -esac +branches_format="%(color:yellow)%(refname:short)%(color:reset)" +commits_format="%C(red bold)%h %C(bold blue)%an %C(bold green)%ad %Creset%s" -COUNT=0 -while getopts "n:" opt; do - case ${opt} in - n ) - if ! [[ $OPTARG =~ ^[0-9]{1,}$ ]]; then - echo "-n should be an integer." - exit 1 - fi - COUNT=${OPTARG} - shift - ;; - esac -done -shift $((OPTIND-1)) +# The primary branch +mainormaster() { + (git branch --format '%(refname:short)' --sort=-committerdate --list master main; echo main) | head -n1 || echo main +} -format="\ -%(HEAD) \ -$branch|\ -%(color:bold red)%(objectname:short)%(color:reset) \ -%(color:bold green)(%(committerdate:relative))%(color:reset) \ -%(color:bold blue)%(authorname)%(color:reset) \ -%(color:yellow)%(upstream:track)%(color:reset) \ -%(contents:subject)" +uniqcommits_cmd="git log --date=human --color=always --format='$commits_format' --no-merges origin/$(mainormaster)..{1}" -lessopts="--tabs=4 --quit-if-one-screen --RAW-CONTROL-CHARS --no-init" +diffbranch_cmd="git diff --color=always origin/$(mainormaster)...{}" +# Progressive enhancement if you have delta or diff-so-fancy +if command -v delta >/dev/null 2>&1; then + diffbranch_cmd="$diffbranch_cmd | delta" +elif command -v diff-so-fancy >/dev/null 2>&1; then + diffbranch_cmd="$diffbranch_cmd | diff-so-fancy" +fi -git for-each-ref \ - --color=always \ - --count=$COUNT \ - --sort=-committerdate \ - "refs/heads/" \ - --format="$format" \ - | column -ts '|' \ - | less "$lessopts" +# fzf basic inspiration: +# - https://github.com/junegunn/fzf/wiki/Examples#git, https://github.com/junegunn/fzf/wiki/Examples-(fish)#git +# Hardcore inspiration: +# - https://github.com/junegunn/fzf-git.sh -# The above command: -# for all known branches, -# (force coloring on this, especially since it's being piped) -# optionally, specify the number of branches you want to display -# sort descending by last commit -# show local branches (change to "" to include both local + remote branches) -# apply the formatting template above -# break into columns -# use the pager only if there's not enough space +_browse_branches() { + git for-each-ref --color=always --sort=-authordate "refs/heads/" --format="$branches_format" \ + | fzf-tmux --ansi -p80%,60% -- \ + --layout=reverse --multi --height=90% --min-height=20 \ + --border-label-pos=2 --border-label '🌲 Branches' --border \ + --no-hscroll --no-multi \ + --preview-window='right,70%,border-left,border-rounded' --preview="$uniqcommits_cmd" --preview-label="Commits unique to branch" \ + --header $'ENTER (checkout)\nCTRL-O (show branch diff)\n' \ + --bind 'preview-scroll-up:preview-up+preview-up+preview-up' \ + --bind 'preview-scroll-down:preview-down+preview-down+preview-down' \ + --bind "ctrl-o:preview:$diffbranch_cmd" +} + +chosen_branch="$(_browse_branches)" +if [[ -n "$chosen_branch" ]]; then + echo git checkout "$chosen_branch" + git checkout "$chosen_branch" +fi diff --git a/git-recent-og b/git-recent-og new file mode 100755 index 0000000..68ba7f7 --- /dev/null +++ b/git-recent-og @@ -0,0 +1,62 @@ +#!/bin/bash + +## +## git-recent +## +## list all local branches, sorted by last commit, formatted reall purdy +## + +# Windows needs more basic format (#8, git-for-windows/git#865) +case $(uname -s) in + CYGWIN*|MINGW*|MSYS*) + branch='%(refname:short)' + ;; + *) + branch='%(color:yellow)%(refname:short)%(color:reset)' + ;; +esac + +COUNT=0 +while getopts "n:" opt; do + case ${opt} in + n ) + if ! [[ $OPTARG =~ ^[0-9]{1,}$ ]]; then + echo "-n should be an integer." + exit 1 + fi + COUNT=${OPTARG} + shift + ;; + esac +done +shift $((OPTIND-1)) + +format="\ +%(HEAD) \ +$branch|\ +%(color:bold red)%(objectname:short)%(color:reset) \ +%(color:bold green)(%(committerdate:relative))%(color:reset) \ +%(color:bold blue)%(authorname)%(color:reset) \ +%(color:yellow)%(upstream:track)%(color:reset) \ +%(contents:subject)" + +lessopts="--tabs=4 --quit-if-one-screen --RAW-CONTROL-CHARS --no-init" + +git for-each-ref \ + --color=always \ + --count=$COUNT \ + --sort=-committerdate \ + "refs/heads/" \ + --format="$format" \ + | column -ts '|' \ + | less "$lessopts" + +# The above command: +# for all known branches, +# (force coloring on this, especially since it's being piped) +# optionally, specify the number of branches you want to display +# sort descending by last commit +# show local branches (change to "" to include both local + remote branches) +# apply the formatting template above +# break into columns +# use the pager only if there's not enough space diff --git a/git-recent-with-fzf-and-diff b/git-recent-with-fzf-and-diff deleted file mode 100755 index e406281..0000000 --- a/git-recent-with-fzf-and-diff +++ /dev/null @@ -1,52 +0,0 @@ - -#!/bin/bash - -# -# git recent upgraded. lists unique commits to that branch. and the branch diff. -# -# run it: -# git recent-with-fzf-and-diff # or alias it -# then within it -# `ctrl-o` to show the diff of that branch against the origin/main (or origin/master) -# `enter` to git checkout that branch -# - - -branches_format="%(color:yellow)%(refname:short)%(color:reset)" -commits_format="%C(red bold)%h %C(bold blue)%an %C(bold green)%ad %Creset%s" - -mainormaster() { - (git branch --format '%(refname:short)' --sort=-committerdate --list master main; echo main) | head -n1 || echo main -} - -stat_cmd="git diff --color=always --stat origin/$(mainormaster)...{}" -diffcommits_cmd="git log --date=human --color=always --format='$commits_format' --no-merges origin/$(mainormaster)..{1}" -diffbranch_cmd="git diff origin/$(mainormaster)...{} | delta" - -# fzf basic inspiration: -# - https://github.com/junegunn/fzf/wiki/Examples#git, https://github.com/junegunn/fzf/wiki/Examples-(fish)#git -# Hardcore inspiration: -# - https://github.com/junegunn/fzf-git.sh - - -_browse_branches() { - local preview_cmd="$diffcommits_cmd" # Default preview: commit log - - git for-each-ref --color=always --sort=-authordate "refs/heads/" --format="$branches_format" \ - | fzf-tmux --ansi -p80%,60% -- \ - --layout=reverse --multi --height=90% --min-height=20 \ - --border-label-pos=2 --border-label '🌲 Branches' --border \ - --no-hscroll --no-multi \ - --preview-window='right,70%,border-left,border-rounded' --preview="$diffcommits_cmd" --preview-label="Commits unique to branch" \ - --header $'CTRL-O (show branch diff)\nENTER (checkout)\n' \ - --bind 'preview-scroll-up:preview-up+preview-up+preview-up' \ - --bind 'preview-scroll-down:preview-down+preview-down+preview-down' \ - --bind "ctrl-o:preview:$diffbranch_cmd" -} - - -chosen_branch="$(_browse_branches)" -if [[ -n "$chosen_branch" ]]; then - echo git checkout "$chosen_branch" - git checkout "$chosen_branch" -fi diff --git a/readme.md b/readme.md index d900e2c..91e4f91 100644 --- a/readme.md +++ b/readme.md @@ -1,17 +1,53 @@ -# git-recent +# git recent -Type `git recent` to see your latest local git branches +Speedily browse your latest local git branches, `checkout` with Enter. Also view branches unique commits, and optionally the diff against main. -## Usage +[Demo video of git recent 2.0](https://github.com/user-attachments/assets/441f0b9b-8469-41bd-a826-0bb0cd7c7de8) + +`git recent` now offers an interactive UI (thx to [fzf](https://github.com/junegunn/fzf)) for browsing recent branches, seeing differences, and `checkout`'ing your selection. + +See a diff of your branch vs main with `ctrl-o`. If you have [delta](https://dandavison.github.io/delta//) it'll use that for formatting, but will fallback, too. + +If you're like me, mostly using classic git commands, then `git recent` provides a nice upgrade for browsing/selecting recent branches. But if you're a TUI fan using [git-fuzzy](https://github.com/bigH/git-fuzzy), [`lazygit`](https://github.com/jesseduffield/lazygit) or [`tig`](https://jonas.github.io/tig/) or [`fzf-git`](https://github.com/junegunn/fzf-git.sh), well… this probably isn't an upgrade. :p (But you can certainly [read the source](/git-recent) quickly!) + + +### Installation + +`fzf` is required for 2.0. TBH, it's a fantastic tool; those [shell key bindings](https://junegunn.github.io/fzf/shell-integration/) are _delightful_. That said, if you're dependency-averse, the older version below, [`git recent-og`](#git-recent-og), may be for you. + +* Mac: `brew install fzf` +* Linux: `sudo apt-get install fzf` +* Windows: `choco install fzf` + +Then, do one of these: + +* Manual: Grab the `git-recent` script from this repo and put it anywhere in your `$PATH`. Run `chmod +x git-recent`. +* Via NPM: `npm install --global git-recent` +* ~Homebrew: `brew install git-recent`~ _(Coming soon! Updated for 2.0)_ + +### Usage git recent +Hit `Enter` to checkout the selected branch. + +Type or use arrow keys to navigate your list of branches. + +Hit `ctrl-o` to see the branch diff. + +-------------------------------- + +# `git recent-og` + +`git recent-og` is the [OG](https://www.urbandictionary.com/define.php?term=OG) `git recent`, released back in 2016. Now it's been renamed to `git recent-og`. + + git recent-og Optionally, add `-n` to see the most recent `` branches - git recent -n5 + git recent-og -n5 -![git-recent screenshot](https://cloud.githubusercontent.com/assets/39191/17446638/039d4cee-5aff-11e6-9e11-4294f0020513.png) +![git-recent-og screenshot](https://cloud.githubusercontent.com/assets/39191/17446638/039d4cee-5aff-11e6-9e11-4294f0020513.png) If you're a Windows user, you need to use [Git Bash](https://git-scm.com/downloads) or similar shell in order to effectively use this utility. @@ -28,6 +64,8 @@ On Mac, you can install with homebrew: brew install git-recent +---------- + ## If you like this you may also be interested in... - [`git open`](https://github.com/paulirish/git-open) - Open the repo website in your browser @@ -37,8 +75,10 @@ On Mac, you can install with homebrew: Copyright Paul Irish. Licensed under MIT. - ## Changelog -- **2016-05-16** - added to [paulirish/dotfiles](https://github.com/paulirish/dotfiles/commit/1ca1ff760832af558447145fa2a367046b1829d2) -- **2016-08-05** - released in standalone repo and published to npm +- **2025-02** - 2.0 upgrade with fzf integration. 1.0 binary is now available as `git recent-og`. +- **2019-06** - Last bugfix for 1.0 landed. Been stable since then. +- **2018-10** - Added count `-n` parameter +- **2016-08** - released in standalone repo and published to npm +- **2016-05** - added to [paulirish/dotfiles](https://github.com/paulirish/dotfiles/commit/1ca1ff760832af558447145fa2a367046b1829d2)