The tig config that delights you!
The fastest way to rebase using tig, or any other tool
Fixup, squash, move one, move many, reword, edit, drop, splice, dice, all from tig!
"I wanted the power of git-interactive-rebase-tool from within tig." β That's why this exists
Never leave tig again (to run your favorite git commands)
'Generic' view bindings (that work from any view):
Binding | Description |
---|---|
<C-r> |
Run interactive-rebase-tool from revision under cursor (and quit tig if conflicts or rebase doesn't complete) |
& |
Reword revision under cursor |
* |
Edit revision under cursor (and quit tig) |
+ |
Fixup staged to revision under cursor (and quit tig if conflicts) |
<C-t> |
Create a WIP commit with uncommitted changes |
^ |
Pop youngest (latest) commit if WIP commit |
x |
Copy SHA from revision under cursor to clipboard |
T |
Show datetime format and make date column wider, e.g., 2023-01-15 15:23 |
R |
Show relative format and make date column narrower, e.g., 3 hour |
v |
Open line under cursor in gVim (prefers gvim-open-kindness if installed) |
V |
Moved built-in :show-version from v to V , to make our gVim command easier to use |
e |
Like v , but opens line under cursor in terminal EDITOR |
P |
Copy file path to clipboard |
. |
Temporarily shells-out (shows terminal session; useful for reviewing previous command output) |
C |
Runs git commit -v |
<C-o> |
Drop the selected revision |
'Main' and 'diff' view bindings:
Binding | Description |
---|---|
! |
Make the selected revision the most recent revision (aka, bubble-up) |
'Main' and 'diff' view bindings you can use to move one or more commits, and optionally squash or fixup those commits:
Binding | Description |
---|---|
[ |
Selects a single commit for the \ command (sets a special "π©-SELECTED-REV-π©" tag) or to mark the start of range of commits (use ] to mark the other end of the range) |
] |
After [ , use to mark a range of commits for the \ command (removes the "π©-SELECTED-REV-π©" tag and uses "π©-START-HERE-π©" and "π©-UNTIL-HERE-π©" tags to mark the range) |
{ |
Removes all special tags (i.e., "cancel" the [ and ] commands) |
\ |
Selects the target commit and performs an action (see the list that follows) on the single [ commit, or on the range specified by [ and ] |
\
command actions:
-
These actions work on a single commit, or on a range of commits, using the target commit for reference.
-
The special tags are necessary to tell the sequence editor what to do (we could alternatively use a temporary file under the local
.git/
directory, but using tags lets you see which commit(s) you've selected). -
To act on one commit, first use the
[
command to select a commit, then select the target commit and press\
to perform one of the following actions. -
To act on a range of commits, first use the
[
command to select one end of the range, then use]
to select the other end. Finally, select the target commit and press\
to perform one of the following actions:
Action | Description |
---|---|
p |
Cherry pick the selected commit or range of commits (the target commit is ignored) |
b |
Move the selected commit or range of commits (chronologically) before target commit |
a |
Move the selected commit or range of commits (chronologically) after target commit |
t |
Move the selected commit or range of commits (chronologically) to be latest commits |
s |
Squash the selected commit or range of commits into the target commit |
f |
Fixup the selected commit or range of commits into the target commit |
-
Note that, except for cherry-pick, the previous actions only work on the current branch.
- E.g., if you run
tig some-other-branch
, you can only cherry-pick from that branch; you cannot move, squash, or fixup commits.
- E.g., if you run
Masked bindings:
-
The
^
mapping masks tig's built-in:toggle rev-filter
binding [but I testedrev-filter
and it changes nothing for me, so I'm not remapping the command elsewhere, like I did withV
/:show-version
] -
The
C
mapping masks tig's built-in?git cherry-pick %(commit)
binding.- Use the
\
action to cherry-pick; and useC
to callgit commit -v
.
- Use the
-
The
v
mapping masks tig's built-in:show-version
binding, which is re-bound toV
(so that we can usev
to open the line under the cursor in gVim).
Setting | Description |
---|---|
set commit-order = topo |
Order commits topologically |
set horizontal-scroll = 25% |
Scroll 25% of the view width |
set blame-options = -C -C -C |
Blame lines from other files |
set reference-format = (branch) <tag> [remote] |
Show branch names in () and tag names in <> |
set line-graphics = utf-8 |
Choose UTF-8 glyphs for the revision history/ancestry marks |
set ignore-case = smart-case |
Naturally |
set blame-view = date:default author:abbreviated file-name:auto id:yes,color line-number:yes,interval=5 text |
Configure blame view columns |
set diff-options = --src-prefix=a/ --dst-prefix=b/ |
Undoes git-smart .gitconfig setting that breaks tig-newtons 'v' command |
If you want to use certain bindings (including bubble-up <!>
, and most of
the rebase commands), you'll need to install tig-newtons to a specific path:
~/.kit/git/tig-newtons
Or you'll need to use the TIGNEWTONSPATH
environ, e.g.,
TIGNEWTONSPATH=path/to/tig-newtons tig
Which you could also export from your Bashrc or similar:
export TIGNEWTONSPATH=path/to/tig-newtons
The tig/config
has to use full paths to source
files,
so you need to generate a custom tig/config
file.
Run the customize.sh command to generate the file. It uses a template (tig/config.customize) to generate a similar file that uses your local project's path.
-
After cloning the project, change to the root directory and create your
tig/config
file:cd path/to/tig-newtons ./customize.sh > tig/config
XDG_CONFIG_HOME=path/to/tig-newtons/tig/config tig
mkdir -p ~/.config/tig
ln -s /path/to/tig-newtons/tig/config ~/.config/tig/config
Edit ~/.config/tig/config
and add:
source /path/to/tig-newtons/tig/config
For commands that use EDITOR
, if you'd like to use a different editor
than your normal EDITOR
, set the TNEWTONS_EDITOR
environ, e.g.,
export TNEWTONS_EDITOR='nvim --noplugin'
tig
Or:
TNEWTONS_EDITOR='nvim --noplugin' tig
This setting applies to the rebase commands, as well as the commit (C
)
and reword (&
) commands.
The GVim open command (v
) prefers gvim-open-kindness
if available, otherwise it falls back on raw gvim
calls.
-
You can clone and install
gvim-open-kindness
from sources: -
The
gvim-open-kindness
command adds a few niceties, such as fronting the Neovim, Neovide, or GVim window after opening the file (for macOS and X Windows; Wayland support coming). -
If
gvim-open-kindness
is not installed, the command will fallback to looking for a GVim instance. Then you would have to manually switch to GVim if the opened file is sent to a running instance. -
Whether or not you install
gvim-open-kindness
, you can use theGVIM_OPEN_SERVERNAME
environ to set the GVim--servername
, e.g.,:GVIM_OPEN_SERVERNAME="my-gvim-server" mropen
(But if you enjoy using Neovim or Neovide, consider installing
gvim-open-kindness
for a Neovim-friendlyv
command.)
Git might complain during garbage collection after you've used
tig
and tig-newtons
a lot.
-
To be honest, the author has only seen this happen once in their own experience, but it's documented here should it happen again.
-
If you see the following warning after git-commit:
warning: The last gc run reported the following. Please correct the root cause and remove .git/gc.log Automatic cleanup will not be performed until the file is removed. warning: There are too many unreachable loose objects; run 'git prune' to remove them.
There's likely a very reasonable explanation (and Git maybe should ease off a bit, especially if you're a power tigger).
-
Git's problem is
too many unreachable loose objects
.-
The most well known type of "loose object" is the dangling commit.
This will happen because of rebase β all those original commits that were rebased are no longer part of any branch, and are therefore considered loose commits, or dangling commits.
-
There's also another type of loose object, the dangling blob.
A dangling blob is simply a change to staging that is never committed.
That is, from the first
git-add
until the subsequentgit-commit
, all the changes are recorded as blobs.So whether you use
git add <file>
, orgit add --patch
, or usetig
to stage line-by-line (1
), by the chunk-part (2
), or by the chunk (u
), each of those actions creates a dangling blob. -
The author uses single-line staging most of the time, and I rebase so, so often, that I had 700 dangling commits, and ten times as many dangling blobs in the project that I was hacking on when Git barked about "too many loose objects".
-
To probe your situation, run
git fsck
to see the dangling objects.- Use
git show <blob>
to see blobs, andtig <commit>
to see comits.
- Use
-
-
To resolve the situation, run something like this:
git prune git fsck | wc -l # EXPECT: 0 command rm .git/gc.log # Git will eventually run git-gc and be happy
-
lazygit
is another Git TUI you might find interesting:
man tig
man tigrc
man tigmanual
https://jonas.github.io/tig/doc/tigrc.5.html
https://github.com/jonas/tig/blob/master/tigrc
tig-newtons
maintained by DepoXy dev
environment orchestration project