AnSwErYWJ's Blog

Git速查手册(第二版)

字数统计: 2.9k阅读时长: 63 min
2019/02/12

本文是对之前Git速查手册的更新,增加了一些这段时间使用到的命令。

配置git

笔者使用的是v2.1.0,推荐大家使用v1.8以上的版本。 查看git版本:

1
$ git --version

配置命令git config分为三个级别:

1
2
3
--system : 系统级,位于 /etc/gitconfig .
--global : 用户级,位于 ~/.gitconfig .
--local : 仓库级,位于 repo/.git/config ,default并且优先级最高.

首先需要删除global用户信息,防止不同git软件之间的冲突:

1
2
$ git config --global --unset user.name
$ git config --global --unset user.email

设置用户信息.若同时使用gitlab和github,推荐配置local用户信息:

1
2
$ git config --local user.name "username"
$ git config --local user.email "email"

git支持https和ssh等协议.https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,而ssh支持的原生git协议速度最快。
检查本机SSH公钥:

1
$ ls ~/.ssh

若存在,则将id_rsa.pub添加到github的SSH keys中。若不存在,则生成:

1
$ ssh-keygen -t rsa -C "your_email@youremail.com" 

当ssh配置完成后,再次检查ssh连接情况:

1
2
$ ssh -T git@github.com
Hi! You’ve successfully authenticated, but GitHub does not provide shell access.

若出现上述信息,则表示设置成功。
若使用https访问, 则进行如下配置,并且设置超时时间避免重复输入密码:

1
2
$ git config --global http.sslverify false
$ git config --global credential.helper 'cache --timeout=3600'

设置可视化diff和merge工具, linux系统上推荐使用meld或者diffuse:

1
2
$ git config --global diff.tool meld
$ git config --global merge.tool meld

保存用户名,密码, 避免每次pull/push操作都需要手动输入:

1
2
$ git config --global credential.helper store
# 执行上免的命令后, 下次操作输入的密码会被保存

设置颜色,利于使用:

1
$ git config --global color.ui.true

设置别名:

1
$ git config --global alias checkout co 

上面的命令将checkout设置为别名co

最后,查看一下所有的设置:

1
2
3
$ git config --local --list
$ git config --global --list
$ git config --system --list

工作流

工作流

工作区就是你的本地仓库文件夹,不过其中的.git目录不属于工作区,而是版本库。里面存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
现在来解释一下前面的添加和提交操作:

  1. git add把文件添加进去,实际上就是把文件修改添加到暂存区;
  2. git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
    因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

基本操作

获取远程仓库:

1
$ git clone git@github.com:USERNAME/repo.git

将本地的仓库添加到远程:

1
2
3
$ cd repo
$ git init
$ git remote add origin git@github.com:USERNAME/repo.git

origin就是一个名字,是git为你默认创建的指向这个远程代码库的标签。

添加修改:

1
2
3
$ git add <filename> 
$ git add . # 添加当前目录所有修改过的文件
$ git add * # 递归地添加执行命令时所在的目录中的所有文件

提交修改:

1
2
$ git commit -m "commit message"
$ git commit -am "commit message"

commit message的填写可以参考写好 Git Commit 信息的 7 个建议
am将添加和提交合并为一步,但只对本来就存在的文件有效。

推送修改:

1
$ git push -u origin <feature-branch-name>

-u选项可以将本地分支与远程分支关联,下次git pull操作时可以不带参数.具体参见这里

查看远程仓库:

1
2
3
$ git remote -v
origin git@github.com:USERNAME/repo.git (push)
origin git@github.com:USERNAME/repo.git (fetch)

fork后同步上游仓库的更新:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 第一次需要添加上游仓库
$ git remote add upstream git@github.com:USERNAME/repo.git

$ git remote -v
origin git@github.com:USERNAME/repo.git (push)
origin git@github.com:USERNAME/repo.git (fetch)
upstream git@github.com:USERNAME/repo.git (push)
upstream git@github.com:USERNAME/repo.git (fetch)

$ git fetch upstream
$ git difftool <branch-name> upstream/master
$ git merge upstream/master
$ git mergetool

引用公共代码:
代码引用在git上有两种方式:submodulesubtree,推荐使用subtree方式。

1
2
3
4
5
6
7
8
9
# 第一次初始化
$ git remote add -f <remote-subtree-repository-name> <remote-subtree-repository-url>
$ git subtree add --prefix=<local-subtree-directory> <remote-subtree-repository> <remote-subtree-branch-name> --squash

# 同步subtree的更新
$ git subtree pull --prefix=<local-subtree-directory> <remote-subtree-repository> <remote-subtree-branch-name> --squash

# 推送到远程subtree库
$ git subtree push --prefix=<local-subtree-directory> <remote-subtree-repository> <remote-subtree-branch-name>

使用标签

查看标签 :

1
$ git tag

创建标签 :

1
2
$ git tag -a <tagname> -m "tag message" # 创建标签在当前最新提交的commit上
$ git tag -a <tagname> -m "tag message" <commit id> # 创建标签在指定的commit上

推送标签到远程:

1
2
$ git push origin <tagname> # 推送一个本地标签
$ git push origin --tags # 推送全部未推送过的本地标签

删除标签:

1
2
$ git tag -d <tagname> # 删除一个本地标签;
$ git push origin :refs/tags/<tagname> # 删除一个远程标签。

撤销与回退

查看当前仓库状态:

1
$ git status

查看文件更改:

1
2
$ git difftool <filename>
$ git mergetool <filename>

查看提交历史:

1
2
$ git log
$ git log --pretty=oneline #只保留commit id 和 commit message

撤销工作区Tracked files的修改:

1
$ git checkout -- <filename>

撤销工作区Untracked files的修改:

1
2
3
4
5
6
7
8
9
#####
# n:查看将会删除的文件,防止误删
# f:Untracked的文件
# d:Untracked的目录
# x:包含gitignore的Untracked文件和目录一并删掉,慎用!
#####

git clean -nfd
git clean -fd

回退版本区(git commit)和暂存区(git add),不删除工作空间代码:

1
2
$ git reset --mixed HEAD^ # --mixed为默认参数
$ git reset HEAD^

回退版本区(git commit),暂存区(git add)不回退,不删除工作空间代码:

1
$ git reset --soft HEAD^

回退版本区(git commit)和暂存区(git add),并删除工作空间代码(不包括Untracked files),执行后直接恢复到指定<commit-id>状态:

1
$ git reset --hard <commit-id>

HEAD表示当前版本,HEAD^表示上个版本,HEAD^^表示上上个版本,上100个版本可以表示为HEAD~100以此类推。

回退版本后,若需要返回原来的版本,会发现找不到未来的commit id,则需要查看操作命令历史进行查找:

1
$ git reflog

从版本库删除文件:

1
$ git rm <filename>

若你的代码已经push到线上,则推荐使用下面这个命令回滚:

1
$ git revert <commit-id>

revert是用一次新的commit来回滚之前的commit,更安全;reset则是直接删除指定的commit,若直接push会导致冲突。

分支

查看所有分支,有*标记的是当前分支:

1
$ git branch -a

创建本地分支:

1
$ git branch <newbranch>

创建并切换本地分支:

1
$ git checkout -b <newbranch>

从标签创建分支:

1
2
$ git branch <branch> <tagname>
$ git checkout <branch> # 切换到新建分支

推送新建本地分支到远程:

1
2
3
$ git push -u origin <remote-branch-name>
or
$ git push --set-upstream origin <remote-branch-name>

删除本地分支:

1
$ git branch -d <branch>

若当前分支因为有修改未提交或其它情况不能删除,请使用-D选项强制删除。

删除远程分支(三种方法):

1
2
3
$ git push origin --delete <remote-branch-name>
$ git push origin -d <remote-branch-name>
$ git push origin :<remote-branch-name>

清除无用的分支:

1
$ git remote prune origin

说明:remote上的一个分支被其他人删除后,需要更新本地的分支列表。

获取远程分支到本地已有分支:

1
$ git branch --set-upstream <local-branch> origin/branch

获取远程分支到本地并新建本地分支:

1
$ git checkout -b <local-branch> <remote-branch>

同步当前分支的更新,使用git pull并不保险:

1
2
3
4
5
6
7
8
# 下载最新的代码到远程跟踪分支, 即origin/<branch-name>
$ git fetch origin <branch-name>
# 查看更新内容
$ git difftool <branch-name> origin/<branch-name>
# 尝试合并远程跟踪分支的代码到本地分支
$ git merge origin/<branch-name>
# 借助mergetool解决冲突
$ git mergetool

同步其它分支的更新,本例拉取master分支更新:

1
2
3
4
$ git fetch origin master
$ git difftool <branch-name> origin/master
$ git merge origin/master
$ git mergetool

查看某个<commit id>属于哪个分支:

1
$ git branch -a --contains <commit id>

暂存

当你需要切换分支时,若当前工作区还有些修改没有完成,又不适合提交的,操作切换分支是会提示出错的.这时就需要将这些修改暂存起来:

1
$ git stash save "message"

查看:

1
$ git stash list

恢复:

1
2
3
$ git stash pop [--index] [stash@{num}] 
or
$ git stash apply [--index] [stash@{num}] # 不删除已恢复的进度.

--index表示不仅恢复工作区,还会恢复暂存区;num是你要恢复的操作的序列号,默认恢复最新进度.

删除进度:

1
2
$ git stash drop [stash@{num}] # 删除指定进度
$ git stash clear # 删除所有

清理仓库

清理无用的分支和标签

1
2
3
4
$ git branch -d <branch-name>
$ git tag -d <tag-name>
$ git remote prune origin
$ git pull

清理大文件

  • 查看git相关文件占用空间:

    1
    2
    $ git count-objects -v
    $ du -sh .git
  • 寻找大文件ID

    1
    $ git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10

    输出的第一列是文件ID,第二列表示文件(blob)或目录(tree),第三列是文件大小,此处筛选了最大的10条

  • 获取文件名与ID映射

    1
    $ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"
  • 从所有提交中删除文件

    1
    2
    $ git filter-branch --tree-filter 'rm -rf xxx' HEAD --all
    $ git pull
  • 清理.git目录:

    1
    $ git gc --prune=now

    tips: 在执行push操作时,git会自动执行一次gc操作,不过只有loose object达到一定数量后才会真正调用,建议手动执行。

处理大型二进制文件

由于git在存储二进制文件时效率不高,所以需要借助第三方组件

忽略特殊文件

当你的仓库中有一些文件,类似密码或者数据库文件不需要提交但又必须放在仓库目录下,每次git status都会提示Untracked,看着让人很不爽,提供两种方法解决这个问题

本地

在代码仓库目录创建一个.gitignore文件,编写规则如下:

1
2
3
tmp/  # 忽略tmp文件夹下所有内容
*.ini # 忽略所有ini文件
!data/ #忽略除了data文件夹的所有内容

全局

在用户目录创建一个.gitignore_global文件,编写规则同.gitignore,并修改~/.gitconfig

1
2
[core]
excludesfile = ~/.gitignore_global

如果添加的忽略对象已经Tracked,纳入了版本管理中,则需要在代码仓库中先把本地缓存删除,改变成Untracked状态

1
$ git rm -r --cached .

.gitignore模版

奇技淫巧

重写历史(慎用!)

1
$ git rebase -i [git-hash| head~n]

其中git-hash是你要开始进行rebasecommithash,而head~n则是从HEAD向前推ncommit

全局更换电子邮件

1
2
3
4
5
6
7
8
9
git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "xxx@localhost" ];
then
GIT_AUTHOR_NAME="xxx";
GIT_AUTHOR_EMAIL="xxx@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD --all

帮助

查看帮助:

1
$ git --help

Reference

  1. 廖雪峰老师的git教程
  2. 常用Git命令清单
  3. Git-Book
  4. Git-Reference
  5. Git push与pull的默认行为
  6. git stash 详解

原文作者:AnSwErYWJ

原文链接:https://answerywj.com/2019/02/12/git-help-v2/

发表日期:2019/02/12 12:02

版权声明:本文采用Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License进行许可.
Creative Commons License

CATALOG
  1. 1. 配置git
  2. 2. 工作流
  3. 3. 基本操作
  4. 4. 使用标签
  5. 5. 撤销与回退
  6. 6. 分支
  7. 7. 暂存
  8. 8. 清理仓库
    1. 8.1. 清理无用的分支和标签
    2. 8.2. 清理大文件
    3. 8.3. 处理大型二进制文件
  9. 9. 忽略特殊文件
    1. 9.1. 本地
    2. 9.2. 全局
  10. 10. 奇技淫巧
    1. 10.1. 重写历史(慎用!)
    2. 10.2. 全局更换电子邮件
  11. 11. 帮助
  12. 12. Reference