• Giacomo Debidda
    • Blog
    • Projects
    • About
    • Contact

My personal Git Memo

20 Jul 2017
  • git

Table of Contents đź“‘
  1. # Find out all commit hashes of the git submodules your branch is pointing at
  2. # Find commit by message string
  3. # Show all commits from an author, in a specified date range
  4. # Fix .git/index.lock
  5. # Permanently remove a file from a repo
  6. # Show branch name in Linux terminal
  7. # Compare a file across 2 branches
  8. # List all commits for a specific file
  9. # Commit only part of a file
  10. # Git hooks
  11. # Discard changes to Git submodules

Here is an unordered list of git commands, configurations, tricks, articles, gotchas that I don’t want to forget.

  • Find out all commit hashes of the git submodules your branch is pointing at
  • Find commit by message string
  • Show all commits from an author, in a specified date range
  • Fix .git/index.lock error
  • Permanently remove a file from a repo
  • Show branch name in Linux terminal
  • Compare a file across 2 branches
  • List all commits for a specific file
  • Configure git aliases
  • Commit only part of a file
  • Git hooks
  • Discard changes to git submodules

# Find out all commit hashes of the git submodules your branch is pointing at

git ls-tree <branch you are currently on>:<path to directory containing the submodules>

Example

git ls-tree master:external

Reference here

# Find commit by message string

git log --all --grep="your commit message here (or part of it)"

Use --all to search across all branches. Don’t use it if you want to restrict the search to the branch you are currently on.

Reference here

# Show all commits from an author, in a specified date range

git log --pretty=format:"%ad - %an: %s" --after="2016-01-31" --until="2017-12-01" --author="John Doe"

Reference here and here

# Fix .git/index.lock

I get this from time to time, and I still haven’t figured out the reason why it occurs.
You just have to remove the index.lock file (not the index!).

rm .git/index.lock

Reference here

# Permanently remove a file from a repo

You should really think twice before performing this operation. Also, keep in mind that this command will override git history.

Anyway, there are some real use cases when this command is useful.

Let’s say that you commit a large file by mistake. You have some stuff to commit and you run a convenient git add . to stash all your changes. Then you forget to review your changes and those changes end up in the commit history. At this point you are still on a local branch, so you can still save the day by removing the file, stashing your changes once again and running a git commit --amend. If you realize your mistake some commits later, but you have not yet pushed them, you can also squash your commits. But if you have already pushed to your remote repository you are out of luck, and that’s when this command could help you.

Let’s suppose that at some point in time you created a README.md for your project, but for some esoteric reason you want to remove it from your project. You can permanently remove your README.md file and make it disappear from your git history with the following command.

git filter-branch --tree-filter 'rm -rf README.md' HEAD

If you now run git status, you will notice that your local branch and your remote branch differ. That’s because your remote branch still has a README.md in its history.

jack@ThinkJack:~/Repos/d3-visualizations(master)$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 26 and 26 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)

Now you have to push your changes to the remote repo. You have to use --force, since this is not a fast-forward commit and you have to rewrite the history of the remote repo.

git push origin master --force

Reference here

# Show branch name in Linux terminal

For this, you have to edit your .bashrc file. It should be in your home directory.

parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[01;31m\]$(parse_git_branch)\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w$(parse_git_branch)\$ '
fi
unset color_prompt force_color_prompt

Reference here

# Compare a file across 2 branches

git difftool <target branch> -- <your file>

For example, if you are on master and want to check a file on your release-01.03.02 branch, run:

git difftool release-01.03.02 -- src/js/index.js

Reference here, and if your file has a different name in 2 different branches, see here.

# List all commits for a specific file

git log --follow filename

Reference here

Configure Git aliases
You can use git config to create your aliases, but there is a faster way.
Add (or edit) the alias section of your .gitconfig file. It should be in your home directory.

These is the alias section in my .gitconfig.

[alias]
st = status
au = add -u
dt = difftool
cm = commit -m
cma = commit --amend --no-edit
co = checkout
# list aliases https://gist.github.com/mwhite/6887990
la = "!git config -l | grep alias | cut -c 7-"

For some other Git aliases, see this wiki.

Reference here and here

# Commit only part of a file

You can use git gui for this. If you don’t have it already, install it with sudo apt-get install git-gui. Here is what I usually do:

  1. git gui
  2. right click on the code you want to commit and select stage lines for commit (or stage hunk for commit)
  3. git stash, to save in the stash all changes that I am not committing right now
  4. git commit
  5. git stash apply
  6. git stash drop

If you like (I personally don’t), you can replace

git stash apply
git stash drop

with

git stash pop

Reference here.

In alternative to git gui, you can use interactive staging from the terminal. I have never tried this.

# Git hooks

I am not an expert on hooks in Git, but I found this really nice article about them.

I think the most useful hooks are

  • pre-push
  • prepare-commit-msg
  • post-commit

It would be nice to have a pre-merge hook, so we could prevent a feature branch from merging into master if certain conditions are not met (e.g. your tests fail). Since a pre-merge hook is not available, you’ll have to [write it]((https://stackoverflow.com/questions/19102714/how-would-i-write-a-pre-merge-hook-in-git).

Reference here.

# Discard changes to Git submodules

I think it happened only once to me, but I had to reset all submodules with this line:

git submodule foreach git reset --hard

Reference here.


  • git
  • RSS
  • GitHub
  • Twitter
  • Linkedin
  • Stack Overflow
Copyright © 2020 – 2022 Giacomo Debidda – All rights reserved