git tips - yszheda/wiki GitHub Wiki

Table of Contents

My Git Tips

Git Low-level Commands

  • Print SHA1 hash:
$ git rev-parse master
$ git rev-parse ca82a6dff817
$ git rev-parse v0.1
ca82a6dff817ec66f44342007202690a93763949
git rev-parse --short HEAD
$ git cat-file -p
$ git ls-files -s
$ git write-tree

Config

Mode

git config --add core.filemode false

Color

git config --global color.ui auto

Editor

git config --global core.editor emacs

Log

$ git log --follow <file>
  • Show diffs first for the HEAD version and then the MERGE_HEAD version:
$ git log --merge --left-right -p [<file>]
  • Search <string></string>:
$ git log -S<string> [--pretty=oneline] [--abbrev-commit] <file>

Diff

$ git diff master bug/pr-1
# equivalent to
$ git diff master..bug/pr-1
$ git diff -S<string>
$ git diff -S"<string>"

Commit

Branch

# rename
git branch -m <newname>

Clone

Tag

$ git tag <tag name> <tag name>^{} -f -m "<new message>"

Merge

  • Policies:
- resolve - recursive - octopus

Squash

git commit --file .git/SQUASH_MSG

Reset

Alterations:

| options | HEAD | index | work_dir | | --soft | Yes | No | No | | --mixed | Yes | Yes | No | | --hard | Yes | Yes | Yes |

$ git cherry-pick <commit>
# on branch master
$ git cherry-pick A..C
# will add A' B' C' commits on branch master

Rebase

Archive

Stash

$ git stash pop
# equivalent to
$ git stash apply
$ git stash drop
# reapply the staged changes
$ git stash apply --index

e.g.

$ git stash apply --index
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#      modified:   index.html
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#      modified:   lib/simplegit.rb
#
  • `git stash --keep-index`: not stash anything that you’ve already staged with the git add command.

e.g.

$ git status -s
M  index.html
 M lib/simplegit.rb

$ git stash --keep-index
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
M  index.html
  • `git --include-untracked/-u`: stash the untracked files as well as the tracked ones.

e.g.

$ git status -s
M  index.html
 M lib/simplegit.rb
?? new-file.txt

$ git stash -u
Saved working directory and index state WIP on master: 1b65b17 added the index file
HEAD is now at 1b65b17 added the index file

$ git status -s
$
  • Creating a Branch from a Stash:
$ git stash branch <branch-name>
$ git stash list --date=local

Clean

# clean untracked files and directories
$ git clean -fd
# If untracked directory is a git repository of its own (e.g. submodule), you need to use -f twice:
$ git clean -ffd

Reflog

$ git reflog expire --expire=now --all
$ git gc

Remote

$ git remote -v
  • Delete a remote branch:
$ git push origin --delete <branch name>
# or
$ git push origin :<branch name>
# if your branch name is the same as some tag name,
# there will be an error like:
# error: dst refspec v2.0 matches more than one.
# Therefore, you have to provide the specified ref like:
$ git push origin :refs/heads/v2.0

bisect

$ git bisect [start | bad | good]

Submodule

Remove Submodule

1. Delete the relevant section from the `.gitmodules` file.

2. Stage the `.gitmodules` changes git add `.gitmodules`.

3. Delete the relevant section from `.git/config`.

4. Run `git rm --cached path_to_submodule` (no trailing slash).

5. Run `rm -rf .git/modules/path_to_submodule`.

6. Commit `git commit -m "Removed submodule <name></name>"`.

7. Delete the now untracked submodule files.

8. `rm -rf path_to_submodule`.

filter-branch

Useful Tips

  • Delete tmp files
$ git filter-branch --tree-filter 'rm -f *~' -- --all
  • Obtain a file from another branch
$ git checkout <branch> -- <file name>
# or (in case you want to rename the file)
$ git show <branch>:<path of file> > <new file name>
  • Overview of what has been changed
$ git whatchanged --since="three days ago" --oneline
$ git whatchanged ORIG_HEAD...HEAD
  • Search
$ git grep
  • Control file tracing
# [add Makefile changes I do not want published]
$ git update-index --no-assume-unchanged Makefile
$ git add -p Makefile
# [add Makefile changes I want published]
$ git commmit
$ git update-index --assume-unchanged Makefile
$ git push
  • If you want to commit the changes after deleting lots of files without using `git rm`:
# easier `git` way
$ git add -u
# or more exactly
$ git status | grep deleted | awk '{print $3}' | xargs git rm
# or (from Jonathan Leffler)
$ git status | sed -n '/^# *deleted:/s///p' | xargs git rm
# or (from Vijay C)
$ git rm $(git ls-files --deleted)
# refer to:
# http://stackoverflow.com/questions/6004453/how-to-remove-multiple-deleted-files-in-git-repository
# http://stackoverflow.com/questions/492558/removing-multiple-files-from-a-git-repo-that-have-already-been-deleted-from-disk
# http://stackoverflow.com/questions/6090732/delete-files-from-git-index-when-they-are-already-deleted-from-fs
# http://stackoverflow.com/questions/3169787/remove-all-deleted-files-from-changed-but-not-updated-in-git
  • Change commit date(修复因系统时间出错而导致的提交时间问题,也可以用来刷Github的streak~XD):
$ git commit --amend --date=<new date>
# e.g.
$ git commit --amend --date="$(date -R)"
  • Fix corrupt git index:
# backup maybe...
$ rm -f .git/index
$ git reset
# or using lower level command
$ git read-tree

# if the problem is with index for packfile, recover it using
$ git index-pack
# Moving to a new branch
# Note: Any changes not committed will be lost.
git branch newbranch      # Create a new branch, saving the desired commits
git reset --hard HEAD~3   # Move master back by 3 commits (GONE from master)
git checkout newbranch    # Go to the new branch that still has the desired commits

# Moving to an existing branch
git checkout existingbranch
git merge master
git checkout master
git reset --hard HEAD~3 # Go back 3 commits. You *will* lose uncommitted work.
git checkout existingbranch
git checkout --orphan <branchname>
git rm --cached -r .
git branch -rd $(git branch -a | grep '{pattern}' | cut -d'/' -f2-10 | xargs)
git branch --merged | egrep -v "(^\*|master|dev)" | xargs git branch -d
git format-patch -1 <sha>
git am < file.patch
git ls-files --others --exclude-standard -z | xargs -0 tar rvf ~/backup-untracked.tar
# Move the current head so that it's pointing at the old commit
# Leave the index intact for redoing the commit.
# HEAD@{1} gives you "the commit that HEAD pointed at before 
# it was moved to where it currently points at". Note that this is
# different from HEAD~1, which gives you "the commit that is the
# parent node of the commit that HEAD is currently pointing to."
git reset --soft HEAD@{1}

# commit the current tree using the commit details of the previous
# HEAD commit. (Note that HEAD@{1} is pointing somewhere different from the
# previous command. It's now pointing at the erroneously amended commit.)
git commit -C HEAD@{1}
git reset e095 -- somefolder
git commit --amend --author "New Author Name <[email protected]>" --no-edit && \
git rebase --continue

lfs.concurrenttransfers

verbose debug info

GIT_SSH_COMMAND="ssh -vvv" git clone example
git -c core.sshCommand="ssh -vvv" pull
GIT_TRACE_PACKET=true git clone ssh://[...]
GIT_CURL_VERBOSE=1

fsck

Search by commit

git branch --contains <commit>
git reflog show --all | grep <commit>

List commits between two commit hashes

git rev-list --ancestry-path 7b4a07a..ecf5891

alias

Convention / Style

Signing

hook

Trouble Shooting

git error: RPC failed; curl 56 GnuTLS

Error in `dpkg-buildpackage`: failed to sign

dpkg-buildpackage -uc -us

error: RPC failed; curl 18 transfer closed with outstanding read data remaining

git config --global http.postBuffer 524288000

gnutls_handshake() failed: Error in the pull function

without username password

# specify caching expire
git config --global credential.helper 'cache --timeout 7200'

git config credential.helper store

ssh

`.ssh/config`:

Host githost
HostName git.host.de
Port 4019
User root

bash auto-complete: `Unknown option: --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config`

source /etc/bash_completion.d/git
# or
source /usr/share/bash-completion/completions/git

HTTP Basic: Access denied

\ No newline at end of file

`git lfs` smudge filter lfs failed

// Skip smudge - We'll download binary files later in a faster batch
git lfs install --skip-smudge

// Do git clone here
git clone ...

// Fetch all the binary files in the new clone
git lfs pull

// Reinstate smudge
git lfs install --force
⚠️ **GitHub.com Fallback** ⚠️