Git速查手册(第三版)

本文是对Git速查手册(第二版)的更新,补充了一些近期使用或者收集的一些命令。


设置Git

版本

Git下载地址:https://git-scm.com/downloads,推荐使用v1.8及以上版本。

查看Git版本:

$ git --version

用户信息

Git配置分为三个级别:

  • --system:系统级,位于 /etc/gitconfig
  • --global:用户级,位于 ~/.gitconfig
  • --local:仓库级,位于 [repo]/.git/config,为默认级别且优先级最高

删除global用户信息,防止不同Git服务之间冲突:

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

配置用户名:

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

保存用户凭证,若同时使用不同的Git服务,不推荐使用:

$ git config --global credential.helper store

执行后,下次操作输入的用户名和密码会被保存,后续不必手动输入用户名和密码。

配置超时时间:

$ git config --global credential.helper 'cache --timeout=3600'

克隆协议

一般Git服务默认都支持SSHHTTPSSSH支持的原生Git协议速度最快,HTTPS除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令。

SSH

检查本机SSH公钥,若存在,则将id_rsa.pub添加到Git服务的SSH keys

$ ls ~/.ssh

若不存在,则生成:

  • 单个Git服务
$ ssh-keygen -t rsa -C "your_email@youremail.com"
  • 多个Git服务
$ ssh-keygen -t rsa -C "your_email@youremail.com" -f "git1_id_rsa"
$ ssh-keygen -t rsa -C "your_email@youremail.com" -f "git2_id_rsa

# 创建配置文件
$ vi ~/.ssh/config
# git1
Host git1.com
HostName git1.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/git1_id_rsa

# git2
Host git2.com
HostName git2.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/git2_id_rsa

配置完成后,再次检查ssh连接情况;若不生效,则重启后再尝试:

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

若出现上述信息,则表示设置成功。

克隆:

$ git clone git@git.server:test.git
HTTPS

关闭ssl校验:

$ git config --global http.sslverify false

克隆:

$ git clone https://git.server/test.git

工具配置

配置diffmerge工具,可以通过git difftool --tool-help查看支持的工具集合,推荐使用meld

  • Linux or MacOS
$ git config --global diff.tool meld
$ git config --global merge.tool meld
  • Windows
> git config --global diff.tool meld
> git config --global merge.tool meld
> git config --global difftool.bc3.path 'C:\Program Files (x86)\Meld\Meld.exe'
> git config --global mergetool.meld.path 'C:\Program Files (x86)\Meld\Meld.exe'
> git config --global difftool.meld.path 'C:\Program Files (x86)\Meld\Meld.exe'

配置显示颜色:

$ git config --global color.ui.true

配置Git操作别名,示例:

$ git config --global alias checkout co 

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

查看所有配置

$ git config --local --list
$ git config --global --list
$ git config --system --list

工作流

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kSn88pqy-1601434622768)(git-work-flow.jpg)]

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

现在来解释一下前面的添加和提交操作:

  1. git add:把文件修改添加到暂存区;
  2. git commit:把暂存区的所有内容提交到当前分支,即版本区;

基本操作

获取远程仓库:

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

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

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

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

添加修改到暂存区:

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

提交修改到版本区:

$ git commit -m "commit message"
$ git commit -am "commit message" # am:将添加和提交合并为一步,但只对本来就存在的文件有效

commit message的填写可以参考写好 Git Commit 信息的 7 个建议

推送修改到远程服务器:

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

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

查看远程仓库:

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

添加上游仓库:

$ git remote add upstream git@github.com:USERNAME/repo.git

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

$ 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方式:

# 第一次初始化
$ 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>

分支

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

$ git branch -a

创建本地分支:

$ git branch <newbranch>

创建并切换本地分支:

$ git checkout -b <newbranch>

从标签创建分支:

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

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

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

删除本地分支:

$ git branch -d <branch>

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

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

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

清除无用的分支:

$ git remote prune origin

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

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

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

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

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

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

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

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

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

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

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

标签

查看标签:

$ git tag

创建标签:

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

推送标签到远程服务器:

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

删除标签:

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

撤销与回退

查看当前仓库状态:

$ git status

查看文件更改:

$ git difftool <filename>
$ git mergetool <filename>

查看提交历史:

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

撤销工作区Tracked files的修改:

$ git checkout -- <filename>

撤销工作区Untracked files的修改:

  • n:查看将会删除的文件,防止误删;
  • f:Untracked的文件;
  • d:Untracked的目录;
  • x:包含gitignoreUntracked文件和目录一并删掉,慎用!;
git clean -nfd

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

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

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

$ git reset --soft HEAD^

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

$ git reset --hard <commit-id>

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

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

$ git reflog

从版本库删除文件:

$ git rm <filename>

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

$ git revert <commit-id>

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

暂存

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

$ git stash save "message"

查看:

$ git stash list

恢复:

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

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

删除进度:

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

清理仓库

清理无用的分支和标签

$ git branch -d <branch-name>
$ git tag -d <tag-name>
$ git remote prune origin
$ git pull

清理大文件

  • 查看git相关文件占用空间:
$ git count-objects -v
$ du -sh .git
  • 寻找大文件ID
$ git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10

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

  • 获取文件名与ID映射:
$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -10 | awk '{print$1}')"
  • 从所有提交中删除文件:
$ git filter-branch --tree-filter 'rm -rf xxx' HEAD --all
$ git pull
  • 清理.git目录:
$ git gc --prune=now

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

处理大型二进制文件

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

忽略特殊文件

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

本地

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

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

.gitignore模版

全局

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

[core]
	excludesfile = ~/.gitignore_global

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

$ git rm -r --cached .

奇技淫巧

重写历史(慎用!)

$ git rebase -i [git-hash| head~n]
$ git push -f # 不强制 push 会多一条 merge 提交信息

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

全局更换电子邮件

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

帮助

查看帮助:

$ git --help

Reference

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

forthebadge

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值