1. Git 基础知识
  2. Git 入门
  3. Git 分支特性

1. Git 基础知识

[ 相关文章|Git 之旅|朱双印个人日志 ]

  1. Git 的特点

    Git 与其他版本控制系统最大的不同在于对待问文件的方式
    其他版本控制软件以文件变化列表的方式存储信息,即记录两个版本文件之间的差异
    Git 以文件快照的方式存储信息,即记录全新的文件
    同时 Git 为了提高效率,如果文件没有发生变化,则不会重新保存文件,而是留下一个指向之前相同文件的链接
    Git 更多的操作是把数据作为一个快照流

  2. Git 的设置

    git config —system:使对应配置针对系统内所有的用户有效
    git config —global:使对应配置针对当前系统用户的所有仓库生效
    git config —local:使对应配置只针对当前仓库有效
    配置个人信息
    git config —global user.nameyishiyu
    git config —global user.emailyishiyu@example.com

2. Git 入门

2.1 获取 Git 仓库

  1. 在现有的目录中初始化 Git 仓库

    初始化后,原文件夹中所有的文件都进入了 untracked 状态
    需要手动 add 并 commit 以完成初始化

  2. 克隆现有仓库

    1
    git clone 仓库url地址 仓库文件夹

    2.2 在 Git 仓库中记录变更

Git 仓库中的文件共有 4 个状态

  • 未跟踪:下一次提交的时候不会记录这个文件,相当于把这个文件删除掉了
  • 未修改:文件未修改
  • 已修改:文件已经修改,但是还没有暂存,下次提交的时候不会记录文件的修改
  • 已暂存:文件已暂存,下次提交时会提交给新的版本

  • git add 命令是一个多功能命令,跟踪文件和暂存文件都是用 add 命令

  • git status 命令可以查看文件状态,-s 参数指定短格式输出

短格式输出文件状态的时候,文件的标记会有两列,左边的一列表示已暂存的状态,右边一列表示未缓存状态
?? 表示文件未被追踪

2.3 忽略文件

可以在仓库文件夹中编写.gitignore 文件以指定需要忽略的文件

规则 含义
空行或以#开头的行 忽略
标准的 glob 模式 简化的正则表达式
以/开头的模式 禁止递归
以/结尾的模式 目录下的所有文件
以!开始的模式 取反
glob 字符 含义
* 匹配零个或多个字符
[abc] 中括号内的字符中的一个
[1-9] 中括号内字符范围内字符
? 任意单个字符
** 匹配嵌套目录
范例 含义
*.a 忽略.a 类型的文件
!lib.a 依然跟踪 lib.a,即使上一行指定忽略
/TODO 忽略当前文件夹中的 TODO 文件
build/ 忽略 build 文件夹中的所有文件
doc/*.txt 忽略 doc 文件夹中的所有的 txt 文件
doc/**/*.pdf 忽略当前 doc/目录下的所有 pdf 文件

2.4 查看已暂存的和未暂存的变更

使用 git dif 命令可以查看已缓存的文件和未缓存的文件之间的差别
但是有一说一感觉还是用 gui 界面看比较舒服,vscode 装个插件基本完美

2.5 提交变更

在修改完文件之后,使用 git add 命令将其添加到暂存区,再使用 git commit 命令提交到仓库

同时 git commit -a 命令可以跳过暂存区,直接把已跟踪的所有文件提交

一般来说直接通过-m 参数添加提交注释就行了
同上,使用 vscode 体验极好

2.6 移除文件

git rm 命令会先把文件从工作区移除,同时把更改添加到暂存区中(直接从文件夹中移除不会添加到暂存区中)

同上,vscode 真香…

2.7 移动文件

1
2
3
4
git rm 命令集成了三条命令:
mv file1 file2
git rm file
git rm file2

同上,vscode 真香…

2.8 查看提交历史

git log 提供查看提交历史功能
-p 选项开启查看差异功能
-n 表示查看多少个记录,n 为数字
—stat 开启查看统计信息
—pretty 指定输出记录的格式
—graph 输出简单分支图

这种带看差异的直接上 vscode

2.9 撤销操作

  1. 覆盖提交

    即上次提交时少提交了某个文件或者 comment 写错了
    可以使用 git commit —amend 选项覆盖提交(只产生一次提交)

  2. 撤销已缓存文件

    在 git status 时会有提示
    即:git reset HEAD \
    但是需要注意不要轻易使用—hard 参数
    没有这个参数是只修改暂存状态
    加上这个参数会同时修改工作区中的文件本身

  3. 撤销对文件的修改

    同上也会有提示
    即:git checkout — \
    但是 git checkout 很危险,它会用之前的版本覆盖指定文件

2.10 远程仓库的使用

命令 作用
git remote 显示所有远程仓库
git remote -v 显示仓库与 url
git remote add 添加新的仓库
git remote show 显示某个仓库详情
git remote rename 重命名远程仓库
git remote rm 删除远程仓库
git retch 从远程仓库中获取数据(不自动合并)
git pull 从远程仓库获取数据并自动合并
git push name branch 把数据推送到远程仓库

2.11 命令别名

1
2
3
4
# 设置之后 ci 等价于 commit
git config --global alias.ci commit
# 设置之后 unstage 等价于 reset HEAD
git config --global alias.unstage 'reset HEAD'

3. Git 分支特性

3.1 基本知识

3.1.1 分支

一个版本分支,不同的分支互不影响
不同分支可以合并,变基

master 分支:系统默认分支(其实并不是特殊分支,可以改成其他名字),常用来发布稳定版本
develop/next 分支:需要手动创建,常用来存放测试版
topic 分支:需要手动创建,用来存放某一主题方向的版本

同时系统维护一个特殊的指针:HEAD 指针
HEAD 本身不是一个分支,而是一个分支指针,指向一个分支,表明当前本地版本所在分支

3.1.2 远程分支

仓库在远程服务器上的分支,区别于本地分支
本地分支名字为:branchname
远程分支需要指明远程仓库:remote/branchname

clone 一个项目之后,系统默认源地址的远程仓库为 origin

跟踪分支:与一个远程分支保持一致的一个本地分支
在跟踪分支上的 push 和 pull 会自动从对应的远程分支操作

3.2 基本操作

3.2.1 创建与删除分支

1
2
3
4
5
6
7
8
9
10
# 在当前节点创建新分支,但是不会切换到新分支
# 本质上是创建了一个行新的分支指针
git branch branchname

# 通过git log可以查看不同分支指向的对象
git log --online --decorate

# 删除一个已被合并的分支只是删掉了一个分支标签
# 不会对提交记录本身有影响
git branch -d branchname

3.2.2 切换分支

1
2
3
4
5
6
7
8
9
# 切换分支命令本质上也是切换HEAD的指向
# branchname分支必须已经创建好了
git checkout branchname

# 可以在切换的同时创建新分支
git checkout -b branchname
# 这条命令相当于
git branch branchname
git checkout branchname

3.2.3 合并分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 合并分支命令把branchname分支合并到当前分支
# 在没有冲突的情况下会直接合并
git merge branchname

# 如果发生了冲突需要解决冲突
# 啊这个是用vim风格的编辑器改的...
git mergetool

# 查看所有分支,已合并的分支,未合并分支
git branch -v
git branch --merged
git branch --no-merged

# 对于已合并的分支,所有没有*的分支都可以直接删除
# 因为其已并入到其他分支中,所以不会丢失任何工作
git branch -d branchname

3.2.4 远程分支操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 添加新的远程仓库
git remote add name url

# 删除远程分支
git remote rm name

# fetch命令会从远程仓库找到所有的本地未包含的数据并更新到本地
# 但是fetch不会自动进行合并,而只是创建新的分支
git fetch remote

# pull命令相当于fetch和merge的结合
# 一般来说直接使用fetch和merge比使用pull更好
git pull remote

# push 命令会推送当前分支到远程仓库上(需要写权限)
git push remote branch
# 如果本地分支与远程分支名称不同
git push remote localname:remotename

3.2.5 跟踪分支

1
2
3
4
5
6
7
8
9
10
11
# 增加一个与一个远程分支相关联的本地分支
# 两条指令等价(第二条是简化版)
git checkout -b [branch] [remote]/[branch]
git checkout --track [remote]/[branch]

# git提供了进一步的简化版本
# 在创建分支时,如果发现与某个远程分支相同,会自动跟踪
git checkout branchname

# 给已存在的分支设置跟踪分支或更换远程分支
git branch -u remote/branch

3.2.6 变基

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#a---b---c---d
# \---e---f
# 如上提交历史,切换到f
# 执行变基操作到d,提交历史会变为
# a---b---c---d---e'---f'
# 即把f的base b变为d(变基字面意思...)
git checkout f
git rebase d

# 变基操作会使得提交历史变得简洁
# 但是有时候也会把事情弄得一塌糊涂(在对远程仓库变基的时候)
# 变基操作的规范是:
# 可以对本地仓库进行一定的变基
# 但是绝对不可以对远程仓库进行变基操作

3.2.7 分离头

正常情况下 HEAD 指针应该指向某一个分支的头位置(即使头位置不是最新位置)
还有一种情况下,HEAD 指针指向某一个提交,而不是一个分支

此时处于分离头状态(detached head)

Git 会提醒:

1
2
3
4
5
6
7
8
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b <new-branch-name>

也就是当前可以随便修改一下,在下一次执行 checkout 命令之后,当前的所有修改和 commit 都会失效且不会影响其他任何分支

如果想要保存当前的工作,可以通过建立新分支的方式来 checkout

1
git checkout -b <new-branch-name>

妙哉妙哉