Git Tips

26 Dec 2020

Personal note to myself:

$ git cherry-pick -x <commit>

Detailed explanation from git help cherry-pick:

When recording the commit, append a line that says “(cherry picked from commit …)” to the original commit message in order to indicate which commit this change was cherry-picked from. This is done only for cherry picks without conflicts. Do not use this option if you are cherry-picking from your private branch because the information is useless to the recipient. If on the other hand you are cherry-picking between two publicly visible branches (e.g. backporting a fix to a maintenance branch for an older release from a development branch), adding this information can be useful.

$ git show branch:file

Where branch can be any ref (branch, tag, HEAD, …) and file is the full path of the file. You can also export that file into another file:

$ git show branch:file > exported_file
# create a diff to current branch HEAD's parent
$ git diff --no-prefix HEAD~ > some.patch

With git grep you can forget about the plain-old grep, provided that you’re in a git repository. Here is some examples how to use git grep.

Use git rebase -i to do interactive rebase - see git help rebase. Please not that this is rewriting history. After changing the local history, you want to publish to the remote repository. To do that, you need to force git push by:

$ git push --force-with-lease
# first do a unwanted commit
$ echo "added one line" >> README
$ git commit -a -m 'added one line to README file'

# let's reset with --mixed option to previous commit
$ git reset HEAD^
$ git status
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   README

no changes added to commit (use "git add" and/or "git commit -a")

# what if we do reset --soft?
$ git reset --soft HEAD^
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

	modified:   README

# how about reset --hard
$ git reset --hard HEAD^
$ git status
On branch master
nothing to commit, working directory clean

# the commit is gone in history! let's check with git log
$ git log --pretty=oneline
d63790eb7feabaf7bed6fc6b46759da109fcd901 first commit

Command git reset has three common options: --soft, --mixed and --hard. If you don’t specify any options, then the default is --mixed, which is the first case in the example given above. No matter what which mode you use, git commit [<mode>] [<commit>] always resets the current branch HEAD to <commit>. In addtion:

Pay attention that both --mixed and --hard are already changing/rewritting history. To learn more git help reset is really your friend.

# listing available tags
$ git tag
0.1.1
0.1.2
0.1.3
0.1.4
0.1.5
0.1.6
0.1.7
0.1.8
0.1.9

# show tag data along with the commit that was tagged
$ git show 0.1.9
tag 0.1.9
Tagger: Henry Huang <keenhenry1109@gmail.com>
Date:   Sun Apr 27 11:17:35 2014 +0200

version 0.1.9

commit 19ae10aa2cf5f6890e831138e901494fa4e68c31
Author: Henry Huang <keenhenry1109@gmail.com>
Date:   Sun Apr 27 11:15:45 2014 +0200

    upgraded to version 0.1.9

# create a tag for the latest/current commit
$ git tag -a 0.2.0

# create a tag for previous commits
# first show commit checksum of previous commits
$ git log --pretty=oneline
2dea6fb9fc2638e4655a00e65167ec8be1e5228c updated tool version
4e570bdf2fa00410fd271ad9fa740ba9782eb539 updated tool installation instruction

# then tag one with a complete commit checksum of part of it
$ git tag -a example -m 'an example release' 2dea6fb9f

# push tags to remote, like github
$ git push origin --tags
# delta debugging using git bisect; try 'git help bisect'
$ git bisect
# rename files and update index
$ git mv old_filename new_filename
# View current remotes
$ git remote -v
origin  git@github.com:user/repo.git (fetch)
origin  git@github.com:user/repo.git (push)
destination  git@github.com:forker/repo.git (fetch)
destination  git@github.com:forker/repo.git (push)

# removing a remote from your local repo
$ git remote rm destination
$ git remote -v
origin  git@github.com:user/repo.git (fetch)
origin  git@github.com:user/repo.git (push)
# print out the diffs on commandline
$ git diff mybranch master -- myfile.txt

# using difftool to compare and show diffs
# -y meaning disable prompt before launching a diff tool
# try 'git help difftool'
$ git difftool -y mybranch master -- myfile.txt

Reference