Advanced Git


More delicate Git commands

Here goes more advanced Git commands not found among the basic ones.

for-each-ref

Display info in .git/refs.

#!/bin/sh

git for-each-ref --shell --format="ref=%(refname)" refs/tags | \
while read entry
do
    eval "$entry"
    echo `dirname $ref`
done

This modified example taken from the one in the official manual pipes

ref=refs/tags/181116
ref=refs/tags/copyBtn0
ref=refs/tags/fa531
ref=refs/tags/solarized

to a while loop. In each iteration, the read command reads each line in the piped output and sets it into the variable entry. The command will exit normally unless it meets an EOF, so that the code inside can be executed. The variable eval set the shell variable ref to the output Git reference name. dirname chops off the tag names (181116, fa531, etc) and returns refs/tags.

ls-files, ls-tree

List files (resp. files in tree). ls-tree displays a table with permissions, Git object types, full SHA1 hashes and file names.

Examples

$ git ls-files
.gitignore
.gitlab-ci.yml
.gitmodules
LICENSE
archetypes/default.md
...
static/js/katex-macros.js
staticman.yml
themes/beautifulhugo

$ git ls-tree origin/master:content/page
100644 blob 1604fbe12feb561b557eab2e7fa5ec95bc68a649    about.md
040000 tree 599c4da34630b2068121a66cf3e82e3e560e3590    advanced-git
040000 tree 10ec0300326e712dc468e4a47826f6056c5eb4a4    bash-commands
100644 blob bd6da925f4118b83fc42eb9af4c33efe53b7ab2c    math-se-comment-templates.md
040000 tree 6a196a2c445425ab4e05940dc84257ad002516fa    sublime

$ git ls-tree -r origin/master:content/page
100644 blob 1604fbe12feb561b557eab2e7fa5ec95bc68a649    about.md
100644 blob 5dccbc2c2dfee0bb50809292019af599aee01e4b    advanced-git/index.md
100644 blob ef7356ed7a22d0acc1fc4bfcf089828852b1b890    bash-commands/180826153752-xubu1804-w400.png
100644 blob d85403db306fde697fd18c19723ca9aa54bd9496    bash-commands/180826153752-xubu1804.png
100644 blob dd65a9113abd99da6586dfb176cda5c2a88392ba    bash-commands/index.md
100644 blob bd6da925f4118b83fc42eb9af4c33efe53b7ab2c    math-se-comment-templates.md
100644 blob 472b544e4497be91d40af7aa937ca8c7f1f9ac53    sublime/index.md

Options for ls-tree:

  • -r: recursive
  • --names-only: print only the file names

Applications

For iteration over cached files only if the file name is “regular enough”. These two commands are synonymous to each other.

Missing EOF detection

Crude version:

!# /bin/sh

g ls-files 1_chapter | \
while IFS= read -r file; do
    echo $file
    tail -c1 $file | od -c
    test `tail -c1 $file` && echo 'missing EOF!' || echo 'has EOF'
done

The output on this GitHub repo would look like

1_chapter/bubbleSort.jl
0000000   )
0000001
missing EOF!
1_chapter/comprehension.jl
0000000  \n
0000001
has EOF

See test for an explanation for what test does.

merge-base

Return the SHA1 hash of the youngest common ancestor of two branches.

$ git merge-base master dev

merge –squash, rebase -i

merge --squash <src> condenses commits into one on the current branch without touching src.

rebase, meaning “re-base”, is analogous to a pot transplant. The -i flag opens an interactive session for that.

Applications

Both merge --squash and rebase can be used for cleaning the commit history. The form can be used if <src> branch is to be thrown away. In rebase -i, one can also squash Git commits.

reflog

Track the SHA1 hash that HEAD represents.

Applications

Find lost commit.

rev-parse

Return the SHA1 hash that Git ref represents.

$ rev-parse FETCH_HEAD  # head of fetched commits

Applications

Verify repo status.

diff

Some advanced options that enable us to spot out differences invisible using normal commands.

  • --ws-error-highlight=<kind>: highlight whitespace errors at lines of type <kind> in git diff’s output. <kind> is a comma-separated list ofnew (+), old (-) and context (neither + nor -) lines. all is a shorthand for old,new,context.
  • --ignore-all-space
  • --ignore-blank-lines
  • --ignore-space-at-eol
  • --ignore-space-change
  • --ignore-submodules