Skip to content

Git命令

基础

初始化仓库

初始化本地仓库:

Bash
git init

初始化默认分支名为master, 可以通过--initial-branch参数更改:

Bash
git init --initial-branch=分支名

克隆远程仓库

Bash
git clone 仓库地址
例:
git clone https://gitee.com/eTank/MES-QZ.git

会自动在当前目录新建项目同名文件夹,如MES-QZ

若出现用户名密码输入框,输入远程仓库的用户名密码。

查看状态

Bash
git status

暂存

修改代码后,将改动文件添加到暂存区:

Bash
git add 文件名

或添加所有改动文件到暂存区:

Bash
git add .

取消暂存

取消暂存,退回到工作区:

Bash
git restore --staged 文件名

取消改动,退回到改动前状态:

Bash
git restore 文件名

删除文件

删除后改动会直接被添加到暂存区:

Bash
git rm 文件名

删除后并取消跟踪:

Bash
#删除跟踪,并保留本地文件
git rm --cached 文件名
#删除跟踪,并删除本地文件
git rm --f 文件名

删除跟踪后的文件在工作区中还是会出现(如git status),想让Git完全忽略此文件,可以使用.gitignore文件。在根目录下创建.gitignore文件,每一行为一个规则,例:

Bash
# 过滤整个 template 文件夹
/template/
# 过滤所有.zip文件 
*.zip
# 过滤某个具体文件
/template/readme.txt

在前面加个!表示需要添加到仓库中的文件,如:

Bash
#只需要管理 template 下的 config.txt 文件,其它文件都不需要跟踪
/template/
!/template/config.txt

如果你不慎在创建.gitignore文件之前就push了项目,那么即使你在.gitignore文件中写入新的过滤规则,这些规则也不会起作用,Git仍然会对所有文件进行版本管理。

提交

提交并备注提交信息:

Bash
git commit -m "备注或说明"
#暂存并提交(已经跟踪的文件)
git commit -am "备注或说明"

查看提交记录

Bash
git log

如果记录过多,则按Page UpPage Down来控制显示,按q退出。

常用参数:

--stat:显示每次更新的修改文件的统计信息,每个提交都列出了修改过的文件,以及其中添加和移除的行数,并在最后列出所有增减行数小计。

-p:显示每个更新间的diff差异,比--stat信息更全。

--shortstat:只显示--stat中最后的行数添加修改删除统计

--name-status:显示新增、修改和删除的文件清单

--graph:显示ASCII图形表示的分支合并历史

--abbrev-commit:仅显示SHA-1的前几个字符

--oneline:一行显示,只显示SHA-1的前几个字符和提交说明

-n:显示前n条

--after=:指定日期之后的记录,如git log --after="2010-10-1",还可以用相对时间,比如"1 week ago""yesterday"

--before=:指定日期之前的记录,同上

--author=:指定提交者的记录,模糊匹配。包含了提交者的名字和email,可用正则。

--grep=:指定描述的记录,模糊匹配

--(空格):指定文件的记录,如:git log -- foo.js bar.js,如果后面的文件路径不会和某个branch产生混淆,可以省略--,如git log foo.js

分支名 --:查看某分支的记录,如 git log master --,如果分支名与文件名相同,系统会提示错 误,可通过--选项来指定给定的参数是分支名还是文件名。比如:在当前分支中有一个名为v1的文件,同时还存在一个名为v1的分支:

`git log v1 --` 此时的v1代表的是分支名字

`git log -- v1` 此时的v1代表的是名为v1的文件

`git log v1 -- v1` 代表v1分支下的v1文件

--no-merges:过滤掉merge commit。默认情况下会输出merge commit

--merges:只显示merge commit

git log <since>..<until>:按范围查看提交。比如:git log master..feature,表示包含了在feature有而在master没有的所有提交,同样,如果是feature..master则表示包含所有master有但是feature没有的提交。如果三个点,表示或的意思,如:git log master...test, 表示查询master或test分支中的提交记录。

git log tag名: 以标签查询提交。如:git log v1.0是查询v1.0之前的提交。加两个点git log v1.0.. 是查询从v1.0以后的提交历史记录(不包含v1.0)

一些alias:

Bash
git config --global alias.lm  "log --no-merges --color --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit"
git config --global alias.lms  "log --no-merges --color --stat --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit"
git config --global alias.ls "log --no-merges --color --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit"
git config --global alias.lss "log --no-merges --color --stat --graph --date=format:'%Y-%m-%d %H:%M:%S' --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Cblue %s %Cgreen(%cd) %C(bold blue)<%an>%Creset' --abbrev-commit"

查找提交

有时程序出现某些bug,可能需要知道到底是哪次提交造成了错误?这次提交都改动了什么造成bug?这个时候就可以使用bisect命令。它的原理是按照二分法不断缩小定位。首先给出查找范围,然后确定问题出在前半部分,还是后半部分,不断执行这个过程,直到范围缩小到某一次代码提交。

先通过log命令查看提交日志,然后用bisect start确定范围:

Bash
git bisect start [终点] [起点]
# 例:
git bisect start HEAD C1

执行后代码库会切换到这个范围间正中的那次提交。通过goodbad 来确定当前代码是否符合查找要求:

Bash
git bisect good
# 或:
git bisect bad

接着代码库会根据命令继续切换到下一个位置。不断重复此过程,知道找到最终的提交,这时会输出:

Bash
xxxxx is the first bad commit

这时就可以检查代码找到问题。

最后可以用reset回到最近的提交:

Bash
git bisect reset

撤销提交

撤销提交可以使用resetrevert,分别适用于本地和远程仓库。

使用reset撤销后,撤销的提交便不存在了,就和没有提交过一样,有点像“时间倒流”。

Bash
git reset [--soft | --mixed | --hard] [HEAD]

reset有三种模式:

  • hard: 退回并撤销所有未提交的修改内容
  • soft: 退回到暂存区
  • mixed(默认): 退回到工作区

例:

Bash
git reset HEAD^                   # 回退所有内容到上一个提交  
git reset HEAD^ hello.js          # 回退 hello.js 文件的版本到上一个提交  
git reset --soft 052e             # 回退到指定提交
git reset –hard HEAD~3            # 回退上上上一个提交
git reset --hard origin/master    # 将本地的状态回退到和远程的一样

reset对远程仓库是无效的,若要同步你的撤销,则需要使用revert

revert会产生一次提交,这次提交的更改就是撤销所作更改,这样便可将更改同步到远程。

例:撤销最近一次提交

Bash
git revert HEAD

HEAD 说明

HEAD 是一个对当前检出记录的符号引用 —— 也就是指向当前你正在工作的位置。 HEAD 总是指向当前分支上最近一次提交记录,通常情况下是指向分支名的。

如果想看 HEAD 指向,可以通过 cat .git/HEAD 查看。 如果 HEAD 指向的是一个引用,还可以用 git symbolic-ref HEAD 查看它的指向。

使用:

  • HEAD 表示当前版本
  • HEAD^ 上一个版本
  • HEAD^^ 上上一个版本
  • HEAD^^^ 上上上一个版本
  • 以此类推...

也可以使用~数字指定返回几步:

  • HEAD~0 表示当前版本
  • HEAD~1 上一个版本
  • HEAD^2 上上一个版本
  • HEAD^3 上上上一个版本
  • 以此类推...

^后也可以跟数字,但和~不同,它是用于指定合并提交记录的某个父提交(Git默认选择合并提交的“第一个”父提交。第一个父提交记录是指合并提交记录正上方的那个提交记录。)

Bash
#检出到 master 的第一个父节点,等同于 HEAD^1
git checkout master^
#检出到 master 的第二个父节点
git checkout master^2

^~还支持链式操作:

Bash
git checkout HEAD~^2~2
# 等同于:
git checkout HEAD~
git checkout HEAD^2
git checkout HEAD~2

存储

存储是将当前的改动保存起来,并还原到改动前的状态。

新建存储:

Bash
git stash -m "备注或说明"
# 包含未跟踪的文件
git stash -u -m "备注或说明"

查看储存列表:

Bash
git stash list

查看存储详情:

Bash
git stash show 存储索引

应用存储:

Bash
git stash apply 存储索引
# apply 后不会删除存储

恢复最近的存储:

Bash
git stash pop
# pop 会应用并删除存储

删除存储:

Bash
git stash drop 存储索引

清空存储:

Bash
git stash clear

添加远程仓库

先在仓库官网新建项目或仓库,获得仓库地址。

Bash
git remote add 仓库名 仓库地址
例:
git remote add origin https://gitee.com/eTank/MES-QZ.git

查看远程仓库信息

Bash
git remote -v

查看远程/本地分支的对应关系

Bash
git remote show origin

拉取

将远程仓库的更新信息全部取回本地(是将本地仓库中的远程分支更新成了远程仓库相应分支最新的状态,它不会更新你的本地分支,也不会修改你磁盘上的文件):

Bash
git fetch origin

当远程分支有新的提交时,使用fetch之后,本地分支并不会随之更新。可以像合并本地分支一样合并远程分支来更新,如:

Bash
git merge origin/master
#或
git cherry-pick origin/master
#或
git rebase origin/master

由于先抓更新再合并到本地分支这个流程很常用,因此Git提供了pull命令来完成这两个操作:

Bash
git pull 远程仓库名 分支名

例:

Bash
#拉取默认远程仓库的默认分支并合并到当前分支
git pull
#拉取远程 origin 的 master 分支,合并到本地的 dev 分支
git pull origin master:dev
#如果远程分支是与当前分支合并,则冒号后面的部分可以省略:
git pull origin master

推送

推送到远程仓库:

Bash
git push
#或
git push origin 分支名

若出现用户名密码输入框,输入远程仓库的用户名密码。

移动提交记录

cherry-pick可以将一些提交复制到当前位置(HEAD)下。

Bash
git cherry-pick <提交1> <提交2> ... <提交n>
#将 c1 和 c2 复制到当前位置:
git cherry-pick C1 C2

提示

cherry-pick可以将提交树上任何地方的提交记录取过来按输入顺序追加到HEAD上(只要不是HEAD上游的提交就没问题)。

交互式 rebase

cherry-pick需要知道提交记录的哈希值,但是在你不清楚提交记录的哈希值时,可以利用交互式rebase从一系列的提交记录中找到想要的记录。

交互式rebase 是指使用带参数 --interactiverebase 命令, 简写为 -i

Bash
#复制最近4次提交记录
git rebase -i HEAD~4

git 会打开文本编辑器并列出将要被复制到目标分支的提交记录,同时会显示每个提交记录的哈希值和提交说明,可以调整提交的顺序、删除不想要的提交、合并提交等。

分支

查看分支

查看本地分支:

Bash
git branch

查看远程分支:

Bash
git branch -r

查看所有分支,包括本地和远程:

Bash
git branch -a

创建分⽀

git branch 新分支名 源分支名

Bash
#基于B1创建分支B2
git branch B2 B1 
#不写源分支就基于当前分支创建
git branch B2

基于当前分支创建新分支并切换:

Bash
#创建后会自动切换到新分支B2
git checkout -b B2

切换分支

Bash
git checkout 分支名

删除分支

Bash
git branch -d 分⽀名

删除远程分支

Bash
git push origin -d 分支名

合并分支

merge

合并目标分支到当前分支:

Bash
git merge 目标分支

rebase

marge不同的是合并后不会增加父节点:它会将源分支的提交记录,“复制”到目标分支下。它的优势是可以创造更线性的提交历史。

Bash
#默认当前分支为源分支
git rebase 目标分支

也可以指定两个分支名,分别表示目标分支、源分支:

Bash
git rebase 目标分支 源分支
# 等同于
git checkout 源分支
git rebase 目标分支

若出现冲突,git 会停止 rebase 并会让你去解决冲突。在解决完冲突后,用 git add 命令去更新这些内容。注意,你无需执行 git commit提交更新,只要用--continue参数继续执行rebase,git会继续剩下的工作:

Bash
git rebase --continue

在任何时候,我们都可以用 --abort 参数来终止 rebase 的行动,并且分支会回到 rebase 开始前的状态:

Bash
git rebase --abort

删除远程不存在的分支

注:删除的是本地分支,即:删除已经不存在的远程分支对应的本地分支

Bash
git remote prune origin

移动分支

Bash
git branch -f 分支名 提交
#例:将 master 分支强制指向 HEAD 的第 3 级父提交
git branch -f master HEAD^3

标签

标签(tag)可以(在某种程度上 —— 因为标签可以被删除后重新在另外一个位置创建同名的标签)永久地将某个特定的提交命名为里程碑,然后就可以像分支一样引用了,就像代码库的一个“锚点”。更难得的是,它们并不会随着新的提交而移动。你也不能检出到某个标签上面进行修改提交,它就像是提交树上的一个锚点,标识了某个特定的位置。

标签有两种:

  • 轻量标签(lightweight): 简单标签,只是某个提交的引用,可以理解为是一个提交的别名
  • 附注标签(annotated) :是存储在git仓库中的一个完整对象,包含打标签者的名字、电子邮件地址、日期时间 以及其他的标签信息。它是可以被校验的,可以使用 GNU Privacy Guard (GPG) 签名并验证

查看标签

Bash
#查看所有标签
git tag
#筛选xxx开头的标签(*为通配符)
git tag -l "xxx*"
#查看标签v1.0的提交信息
git show v1.0

新建标签

创建轻量标签:git tag 标签名 提交名

Bash
#给提交 C1 打上标签 v1.0 
git tag v1.0 C1
#不指定提交则指向HEAD位置
git tag v1.0

创建附注标签:git tag -a 标签名称 提交版本号 -m 附注信息

Bash
#给提交 C1 打上标签 v1.0 
git tag -a v1.0 C1 -m "附注信息"
#不指定提交则指向HEAD位置
git tag -a v1.0 -m "附注信息"

推送到远程仓库:

Bash
#将标签v1.0上传到远程仓库origin
git push origin v1.0
#将所有不在远程仓库origin中的标签上传
git push origin --tags

删除标签

Bash
git tag -d 标签名称

删除远程标签:

Bash
#删除远程仓库origin的v1.0标签
git push origin :refs/tags/v1.0
#或:
git push origin --delete v1.0

签出标签

签出标签一般是为了要在此标签基础上进行其他的开发或操作,因而应以标签为基础版本,新建一个分支,再继续其他的操作:

Bash
#在标签v0.1基础上新建分支B1
git checkout -b B1 v0.1

查看最近标签

describe 命令用以显示离当前位置最近的标签:

Bash
git describe [ref]

ref是任何能被Git识别成提交记录的引用,如果没有指定,默认为当前检出位置(HEAD)。

Bash
git describe master
# 输出:
v1.0-2-g5abb3fe

输出的格式为:<tag>-<numCommits>-g<hash>

  • tag 表示的是离 ref 最近的标签
  • numCommits 表示这个 reftag 相差有多少个提交记录
  • hash 表示的是你所给定的提交记录哈希值前几位

当指定的提交记录上就有某个标签时,则只输出标签名称。

describe默认只显示附注标签,要显示所有的标签,用--tags参数:

Bash
git describe --tags