Everything about Git

Git Pro

复现commit id

How does Git create unique commit hashes, mainly the first few characters?

Git uses the following information to generate the sha-1:

  • The source tree of the commit (which unravels to all the subtrees and blobs)
  • The parent commit sha1
  • The author info (with timestamp)
  • The committer info (right, those are different!, also with timestamp)
  • The commit message

完整说明,另外可参考The anatomy of a Git commit,和 10.1 Git 内部原理 - 底层命令与上层命令对应的英文版本——10.1 Git Internals - Plumbing and Porcelain

执行以下步骤可以复现commit id——

  • git show 获得当前最新的commit信息
  • git cat-file commit HEAD
  • printf "commit %s\0" $(git cat-file commit HEAD | wc -c) 在开头增加commit len\0 文本,长度,NUL-terminated header
  • (printf "commit %s\0" $(git cat-file commit HEAD | wc -c); git cat-file commit HEAD) | sha1sum组合上面两步的内容作为SHA1算法的输入,计算获得的40个字符长度文本就是commitid信息——复现成功


    tree            => 9c435a86e664be00db0d973e981425e4a3ef3f8d (对所有tree对象的递归计算到root节点)
    parents         => [0d973e9c4353ef3f8ddb98a86e664be001425e4a]
    author(with timestamp)          => Christoph Burgdorf <> Sat Nov 8 11:13:49 2014 +0100
    committer(with timestamp)        => Christoph Burgdorf <> Sat Nov 8 11:13:49 2014 +0100
    commit message  => "second commit"

理解Git中的对象概念:Tree Object(对目录、或目录和文件的SHA-1描述。如何获取的?)

├── .git (contents left out)
├── assets
|   ├── logo.png
|   └── app.css
└── app.js

git tree object


Every object consists of three things - a type, a size and content. The size is simply the size of the contents, the contents depend on what type of object it is, and there are four different types of objects: “blob”, “tree”, “commit”, and “tag”.

git write-tree Create a tree object from the current index. returns the hash of the top level tree.

git ls-tree List the contents of a tree object. 可以使用 git cat-file -p treehash起到同样的作用

git cat-file Provide content or type and size information for repository objects

joechin@Gebitang MINGW64 /e/0daywork/gitinit (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   h.txt
        new file:   lib/lealone.png

joechin@Gebitang MINGW64 /e/0daywork/gitinit (master)
$ git write-tree

joechin@Gebitang MINGW64 /e/0daywork/gitinit (master)
$ git ls-tree f6da73
100644 blob ce013625030ba8dba906f756967f9e9ca394464a    h.txt
040000 tree 5de66da52a71d943871ac3753fbed006ee0688f4    lib

joechin@Gebitang MINGW64 /e/0daywork/gitinit (master)
$ git cat-file tree f6da736647be31514378f51704936fcf40171a07
100644 h.txt▒6%
               ▒۩▒V▒▒▒▒▒FJ40000 lib]▒m▒*q▒C▒▒u?▒▒▒▒▒



Filename too long in Git for Windows

Filename too long in Git for Windows

使用管理员权限执行git config --system core.longpaths true修复此问题。

error: could not lock config file C:/Program Files/Git/mingw64/etc/gitconfig: Permission denied

git clone sonarqube源码时,提示

Resolving deltas: 100% (498459/498459), done. fatal: cannot create directory at ‘server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v84/permissiontemplates/fk/permtplcharacteristics/AddUniqueIndexOnTemplateUuidAndPermissionKeyColumnsOfPermTplCharacteristicsTableTest’: Filename too long warning: Clone succeeded, but checkout failed. You can inspect what was checked out with ‘git status’ and retry the checkout with ‘git checkout -f HEAD’

然后再执行git checkout -f HEAD。今天我守着不完整的代码找半天webhook相关的内容

git http clone方式报错:

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

  • $ git clone --depth 1
  • cd large-repository
  • git fetch --unshallow

git clone with token in command line

work for gitlab at list:

git clone

change remote url

git remote -v
# View existing remotes

git remote set-url origin
# Change the 'origin' remote's URL

git remote -v
# Verify new remote URL

use token from command line

use token from command line

$ git clone
Username: your_username
Password: your_token

fatal: Unable to create ‘/path/my_project/.git/index.lock’: File exists

sto: rm -f ./.git/index.lock

修改commit工具 vim

提交说明信息的时候, linux默认是 nano 编辑器
nano 这个编辑器使用 ctrl + x 来退出

# global
git config --global core.editor vim

# project update: .git/config add--


official doc, from Stackoverflow

git log --since=2018-01-01  --pretty=oneline --author=uername --author=gebitang |wc -l

ssh variant ‘simple’ does not support setting port

update setting for git: git config --global ssh.variant ssh

Git Bash: Could not open a connection to your authentication agent


# need to start ssh-agent first.
eval `ssh-agent -s`

Permission denied (publickey).

添加公钥之后,测试验证时会提示“Permission denied (publickey).”。这是因为还没有将生成的对应的key添加到ssh管理中(默认生成的会自动添加,后续生成的多个rsa文件需要手动添加)

# step 1 start agent first.  "ssh-agent bash" or " eval `ssh-agent` "

joechin@Gebitang MINGW64 ~/.ssh
$ ssh-agent bash

joechin@Gebitang MINGW64 ~/.ssh
$ ssh-add xxx_id_rsa
Identity added: xxx_id_rsa (

# add the_abs_path_of_the_new_RSA_file, such as ~/.ssh/coding_id_rsa
ssh-add coding_id_rsa

# " Could not open a connection to your authentication agent" show, go to step 1

# then it could be cloned normaly.

Fork and Sync Repo

1. git remote add upstream
2. git fetch upstream //download objects and refs from another repository 
3. git merge upstream/master //merge upstream/master to current branch

#meaning of merge
git merge origin master //将origin merge 到 master 上
git merge origin/master //将origin上的master分支 merge 到当前 branch 上 
$ git remote add upstream

$ git remote -v
origin (fetch)
origin (push)
upstream (fetch)
upstream (push)

$ git fetch upstream

$ git merge upstream/master

指定branch clone

git clone -b dawn-2.x

git checkout

test@test~$git checkout -b upcoming origin/upcoming
正在检出文件: 100% (1718/1718), 完成.
分支 'upcoming' 设置为跟踪来自 'origin' 的远程分支 'upcoming'。
切换到一个新分支 'upcoming'

0x0. 命令行单独对不同的文件进行commit操作

git add new.file/modified.file
git commit 

git commit -a 

0x1. 配置github账号


  1. 生成rsa文件时可以指定不同的名称,以保证可以生成使用多个
  2. 需要输入passphrase,否则系统认定不够安全,不允许添加到ssh-agent中
  3. 配置config 文件,支持多个git账号
  4. 如果不进行config的配置,在添加ssh key之后,将统一使用global的设置

ssh config 示例 多个rsa文件时

SSH CONFIG FILE OpenSSH Config File Examples

配置了多个公钥后,需要针对不同的站点进行配置,否则会在git clone等交互操作时依然提示需要输入秘密。

配置了config文件后,idea中会根据这个配置文件使用对应的keyUsing Git integration


# 对于ssh的配置
# Defines for which host or hosts the configuration section applies. 
# The section ends with a new Host section or the end of the file. 
# A single * as a pattern can be used to provide global defaults for all hosts.
    # Specifies the real host name to log into. Numeric IP addresses are also permitted.
    # Defines the username for the SSH connection.
    User gebitang
    # Specifies a file from which the user’s DSA, ECDSA or DSA authentication identity is read. 
    IdentityFile ~/.ssh/id_rsa
    # Specifies the port number to connect on the remote host.
    Port 8201
    # The default is ~/.ssh/identity for protocol version 1, and ~/.ssh/id_dsa, ~/.ssh/id_ecdsa and ~/.ssh/id_rsa for protocol version 2.
    IdentityFile ~/.ssh/gitlab_id_rsa
    IdentityFile ~/.ssh/coding_id_rsa
Host bitbucket
    IdentityFile ~/.ssh/bitbucket_id_rsa

  • ssh配置


ssh-keygen -t rsa -b 4096 -C ""

添加ssh key(id_rsa_xxx、到对应的repository,如github、gitlab,即可保证可以从对应的设备上就可以访问对应的repository。

  • git配置

git config 配置完全局的 --global user.email之后,可以在对应的仓库下,配置当前仓库使用的 和

0x2. commit amend修改commit

使用 git commit –amend 参数可以对最近的提交进行修改。 作用相当于新提交了一个commit。 如果修改前的commit已经被同步过,需要先进行拉取 git pull的操作 否则在推送amend之后的commit时会提示:

$ git push origin master
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to ''
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

0x3. Permission denied (publickey)问题

原因:SSH的配置文件ssh_config中的“IdentityFile“ 与实际情况不相符 生成的一对秘钥,公钥上传到对应的站点后,使用-vt参数进行调试验证

# v for verbose mode, V for version
ssh -vT 

如果clone时使用了https格式,则再次推送时总是会提示输入用户名密码,可以通过git config --list查看,然后修改remote.origin.url的值

0x4. 合并commits


# -i for interactive, 而不是指 其中,-i 的参数是不需要合并的 commit 的 hash 值 
# commitid 可理解为在此commit上进行rebase。即此commit之后的commit都可以进行rebase:)
git rebase -i commitid


0x5. 清理、合并操作

Your local changes to the following files would be overwritten by merge


git clean -d -fx


git merge

0x6. 重新添加已经忽略的文件

git add -f ignored/file/name
git rm --cached file/want/to/be/ignore


git rm


# 先本地删除
rm test.txt
# 在从git删除
git rm test.txt 
# 然后commit提交
git commit "delete test.txt file."
# 本地需要的话,可以更新到gitignore文件中



➜ git status
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
➜ sudo xcodebuild -license
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
➜ sudo /usr/bin/git
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
➜ xcode-select --install
xcode-select: note: install requested for command line developer tools
➜ git:(master) ✗
➜ git:(master) ✗

升级到Big Sur之后git无法使用

到git仓库下执行git status检查时提示找不到git,not a developer tool or in PATH。 搜索了一圈,只有这个比较靠谱


sh: line 1:  3799 Bus error: 10           /Applications/ -sdk /Applications/ -find git 2> /dev/null
git: error: unable to find utility "git", not a developer tool or in PATH

git log历史

git log --oneline # show all logs line by line
git show commit # show the commit detail 

git log commit   # 查询commit之前的记录,包含commit
git log commit1 commit2  # 查询commit1与commit2之间的记录,包括commit1和commit2
git log commit1..commit2 # 同上,但是不包括commit1


  • create empty project
# from 0 to 1
mkdir gotourgo
cd gotourgo
git init
echo "# gotourgo" >>
git add
git commit -m "first commit"
git remote add origin
git push -u origin master

  • add existed one
git remote add origin
git push -u origin master


git clone git@ -b next next


# 修改已提交的commit
git commit --amend
git update-index --assume-unchanged filename
git update-index --no-assume-unchanged filename
git rm -r --cached .idea/
git rm -r --cached 要忽略的文件

git config core.ignorecase false

git remote set-url origin new-url

git rebase -i base-commit-hash

Basic Command line instructions

Git global setup
git config --global "gebitang"
git config --global ""

Create a new repository
git clone
cd simpleweb
git add
git commit -m "add README"
git push -u origin master

Existing folder
cd existing_folder
git init
git remote add origin
git add .
git commit -m "Initial commit"
git push -u origin master

Existing Git repository
cd existing_repo
git remote rename origin old-origin
git remote add origin
git push -u origin --all
git push -u origin --tags


# 删除本地
git branch -d local_branch

# 删除远程 
git push --delete remote_branch_name



# branch A B C
git log --graph --decorate --oneline --simplify-by-decoration A B C
# all 
git log --graph --decorate --oneline --simplify-by-decoration --all

git tag


# 查看所以tag  -l 注意是字母"L",以列表形式列出所有tag的版本号. -n 显示出每个版本号对应的附加说明.
git tag -l -n
# 显示时间
git log --tags --simplify-by-decoration --pretty="format:%ci %d "
# 一行显示
git log --tags --simplify-by-decoration --pretty="format:%ci %d "



git commit --amend --author="John Doe <>"

Rewriting the history is done with “git filter-branch” by walking through the complete history. For each commit, filters are applied after which the changes are re-committed. The different filters allow modifying different parts of the commit.

The following uses “git filter-branch” to filter the history. Instead of manipulating the files to be recommitted like explained in Remove files from git history, this command uses the “–env-filter” to alter the environment in which the re-committing statement takes place.


git clone --bare
cd repo.git


# -f to force rewrite, such as git filter-branch -f --env-filter
git filter-branch --env-filter '

CORRECT_NAME="Your Correct Name"

' --tag-name-filter cat -- --branches --tags

这样修改后,会导致远端与本地所有替换的内容都认为不同,需要重新先 ‘git pull’ 获取一次,当出现’fatal: refusing to merge unrelated histories’的提示时,需要执行’git pull origin master –allow-unrelated-histories’命令,然后修改可能的冲突即可。


git push --force --tags origin 'refs/heads/*'


comments powered by Disqus