3、Git安装与常用命令
ls/ll 查看当前目录
cat 查看文件内容
touch 创建文件
vi vi编辑器(使用vi编辑器是为了方便展示效果,学员可以记事本、editPlus、notPad++等其它编 辑器)
3.1、 Git环境配置
3.1.1 下载与安装
下载地址: https://git-scm.com/download
双击下载的安装文件来安装Git。安装完成后在电脑桌面(也可以是其他目录)点击右键,如果能够看到如下两个菜单则说明Git安装成功。
备注:
Git GUI:Git提供的图形界面工具
Git Bash:Git提供的命令行工具
当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用该用户信息
3.1.2基本配置
-
打开Git Bash
-
设置用户信息
git config --global user.name “yushangxue” git config --global user.email “你的邮箱@qq.com”
查看配置信息
git config --global user.name
git config --global user.email
3.1.3 常用指令配置别名(可选)
有些常用的指令参数非常多,每次都要输入好多参数,我们可以使用别名。
-
打开用户目录(C:\Users\Administrator),创建
.bashrc
文件
部分windows系统不允许用户创建点号开头的文件,可以打开gitBash,执行 touch ~/.bashrc
-
在 .bashrc 文件中输入如下内容:
#用于输出git提交日志
alias git-log='git log --pretty=oneline --all --graph --abbrev-commit'
#用于输出当前目录所有文件及基本信息
alias ll='ls -al'
-
在用户目录 打开gitBash,执行
source ~/.bashrc
3.2、获取本地仓库
要使用Git对我们的代码进行版本控制,首先需要获得本地仓库
1)在电脑的任意位置创建一个空目录(例如test)作为我们的本地Git仓库
2)进入这个目录中,点击右键打开Git bash窗口
3)执行命令git init
4)如果创建成功后可在文件夹下看到隐藏的.git目录。
3.3、基础操作指令
Git工作目录下对于文件的修改(增加、删除、更新)会存在几个状态,这些修改的状态会随着我们执行Git 的命令而发生变化。
本章节主要讲解如何使用命令来控制这些状态之间的转换:
-
git add (工作区 --> 暂存区)
-
git commit (暂存区 --> 本地仓库)
提出疑问?暂存区是干什么的?
在软件开发中,很多时候要求我们停止手头上的活去处理别的事情,但此时代码写到一半,无法commit到分支/主干。此时,Git提供了一个暂时存储的功能,将代码add到暂存区,然后将其放在安全的位置,等到紧急任务处理完毕之后,在切回来处理手头上的工作。
3.3.0 工作区与暂存区
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
先来看名词解释。
工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的gitdemo
文件夹就是一个工作区:
版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
分支和HEAD
的概念我们以后再讲。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
俗话说,实践出真知。现在,我们再练习一遍,先对readme.txt
做个修改,比如加上一行内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
然后,在工作区新增一个LICENSE
文本文件(内容随便写)。
先用git status
查看一下状态:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE
no changes added to commit (use "git add" and/or "git commit -a")
Git非常清楚地告诉我们,readme.txt
被修改了,而LICENSE
还从来没有被添加过,所以它的状态是Untracked
。
现在,使用两次命令git add
,把readme.txt
和LICENSE
都添加后,用git status
再查看一下:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE
modified: readme.txt
现在,暂存区的状态就变成这样了:
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
$ git commit -m "understand how stage works"
[master e43a48b] understand how stage works
2 files changed, 2 insertions(+)
create mode 100644 LICENSE
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
$ git status
On branch master
nothing to commit, working tree clean
现在版本库变成了这样,暂存区就没有任何内容了:
3.3.1、查看修改的状态(status)
作用:查看的修改的状态(暂存区、工作区)
命令形式:git status
3.3.2、添加工作区到暂存区(add)
作用:添加工作区一个或多个文件的修改到暂存区
命令形式:git add 单个文件名|通配符
将所有修改加入暂存区:git add .
3.3.3、提交暂存区到本地仓库(commit)
作用:提交暂存区内容到本地仓库的当前分支
命令形式:git commit -m '注释内容'
3.3.4、查看提交日志(log)
在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的工具是 git log
命令。
最有意思的是 format
,可以定制记录的显示格式。 这样的输出对后期提取分析格外有用——因为你知道输出的格式不会随着 Git 的更新而发生改变:
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
列出了 format
接受的常用格式占位符的写法及其代表的意义。
选项 | 说明 |
---|---|
%H |
提交的完整哈希值 |
%h |
提交的简写哈希值 |
%T |
树的完整哈希值 |
%t |
树的简写哈希值 |
%P |
父提交的完整哈希值 |
%p |
父提交的简写哈希值 |
%an |
作者名字 |
%ae |
作者的电子邮件地址 |
%ad |
作者修订日期(可以用 --date=选项 来定制格式) |
%ar |
作者修订日期,按多久以前的方式显示 |
%cn |
提交者的名字 |
%ce |
提交者的电子邮件地址 |
%cd |
提交日期 |
%cr |
提交日期(距今多长时间) |
%s |
提交说明 |
你一定奇怪 作者 和 提交者 之间究竟有何差别, 其实作者指的是实际作出修改的人,提交者指的是最后将此工作成果提交到仓库的人。 所以,当你为某个项目发布补丁,然后某个核心成员将你的补丁并入项目时,你就是作者,而那个核心成员就是提交者。 我们会在 再详细介绍两者之间的细微差别。
当 oneline
或 format
与另一个 log
选项 --graph
结合使用时尤其有用。 这个选项添加了一些 ASCII 字符串来形象地展示你的分支、合并历史:
$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local
这种输出类型会在我们下一章学完分支与合并以后变得更加有趣。
以上只是简单介绍了一些 git log
命令支持的选项。 列出了我们目前涉及到的和没涉及到的选项,以及它们是如何影响 log 命令的输出的:
选项 | 说明 |
---|---|
-p |
按补丁格式显示每个提交引入的差异。 |
--stat |
显示每次提交的文件修改统计信息。 |
--shortstat |
只显示 --stat 中最后的行数修改添加移除统计。 |
--name-only |
仅在提交信息后显示已修改的文件清单。 |
--name-status |
显示新增、修改、删除的文件清单。 |
--abbrev-commit |
仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 |
--relative-date |
使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 |
--graph |
在日志旁以 ASCII 图形显示分支与合并历史。 |
--pretty |
使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format(用来定义自己的格式)。 |
--oneline |
--pretty=oneline --abbrev-commit 合用的简写。 |
--decorate |
标记会让git log显示每个commit的引用(苹果电脑可能会用到) |
GIT 日志图形化解释
符号解释:
// *表示一个commit, 表示提交是发生在那个分支上的|表示分支前进/表示分叉\表示合入
过程解释:
-
base master: master first commit
-
|/这个符号表示新分支, 可以看见是新增br1: br1-first-commit
-
master前进:master-second-commit
-
master merged into br1
-
master前进:master-third-commit
-
br2前进:br2-first-commit(rebase)
-
br2前进:br2-second-commit(rebase【此commit在rebase后提交】)
3.3.5、版本回退/版本穿梭
文件回退
## 删除文件(如果没有commit的话,是可以回退回来的,因为当前文件并未从本地版本库移除)
git rm 文件名
## 文件恢复
git checkout head 文件名
仓库版本回退
作用:版本切换
命令形式:git reset --hard commitID(版本id)
commitID 可以使用 git-log 或 git log 指令查看
git reflog
# 可以找回被删除的历史提交记录
$ git reflog
8537950 (HEAD -> master) HEAD@{0}: reset: moving to 8537950
bc94e9c HEAD@{1}: reset: moving to bc94e9c
8537950 (HEAD -> master) HEAD@{2}: commit: 5.txt 被删除
bc94e9c HEAD@{3}: reset: moving to bc94e9c
38ca380 HEAD@{4}: commit: 删除1.txt
bc94e9c HEAD@{5}: commit: 第二次提交
d126f4f HEAD@{6}: commit (initial): 提交第一文件1.txt
renwoxing@DESKTOP-9D3GBO0 MINGW64 ~/Desktop/gitdemo (master)
$ git-log
* 8537950 (HEAD -> master) 5.txt 被删除
* bc94e9c 第二次提交
* d126f4f 提交第一文件1.txt
3.3.6、添加文件至忽略列表
一般我们总会有些文件无需纳入Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动
生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以在工作目录
中创建一个名为 .gitignore 的文件(文件名称固定),列出要忽略的文件模式。下面是一个示例(.net 常用的):
.Net 忽略文件
# Build and Object Folders
bin/
obj/
# Nuget packages directory
packages/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.vspscc
*.vssscc
.builds
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help
UpgradeLog*.XML
# Lightswitch
_Pvt_Extensions
GeneratedArtifacts
*.xap
ModelManifest.xml
# Backup file
*.bak
*.dll
Java 忽略文件
# eclipse
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
.factorypath
### IntelliJ IDEA ###
*.iml
*.ipr
*.iws
.idea
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
# java
*.class
# Package Files #
*.war
*.ear
#maven
target/
#gradle
.gradle
build/
gradle/
out/
!gradle/wrapper/gradle-wrapper.jar
.DS_Store
.log
#rebel
rebel.xml
log/
*.log
练习:基础操作
#####################仓库初始化######################
# 创建目录(git_test01)并在目录下打开gitbash
略
# 初始化git仓库
git init
#####################创建文件并提交#####################
# 目录下创建文件 file01.txt
touch ./file01.txt
# 将修改加入暂存区
git add .
# 将修改提交到本地仓库,提交记录内容为:commit 001
git commit -m 'commit 001'
# 查看日志
git log
####################修改文件并提交######################
# 修改file01的内容为:count=1
略
# 将修改加入暂存区
git add .
# # 将修改提交到本地仓库,提交记录内容为:update file01
git commit --m 'update file01'
# 查看日志
git log
# 以精简的方式显示提交记录
git-log
####################将最后一次修改还原##################
# 查看提交记录
git-log
# 找到倒数第2次提交的commitID
略
# 版本回退
git reset commitID --hard
3.4、分支
几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离
开来进行重大的Bug修改、开发新的功能,以免影响开发主线。
3.4.1、查看本地分支
命令:git branch
3.4.2、创建本地分支
命令:git branch 分支名
3.4.4、切换分支(checkout)
命令:git checkout 分支名
我们还可以直接切换到一个不存在的分支(创建并切换)
命令:git checkout -b 分支名
3.4.5、合并分支(merge)
一个分支上的提交可以合并到另一个分支
命令:git merge 分支名称
合并分支前,dev分支与master分支目录情况:
合并两个分支后的目录情况:
再比如说:当前分支是A,执行命令:git merge B,意思就是将B分支上的代码合并至当前分支A。
3.4.6 删除分支
不能删除当前分支,只能删除其他分支
git branch -d b1 删除分支时,需要做各种检查
git branch -D b1 不做任何检查,强制删除 (\慎用)
3.4.7、解决冲突 (难点)
当两个分支上对文件的修改可能会存在冲突(conflict),例如同时修改了同一个文件的同一行,当合并分支后必然出现冲突,这时就需要手动解决冲突,解决冲突步骤如下:
-
处理文件中冲突的地方 (需要开发者人为手动的解决)
-
将解决完冲突的文件加入暂存区(add)
-
提交到仓库(commit)
冲突部分的内容处理如下所示
此时就需要与其他开发者沟通,确认使用哪位开发者修改的内容,确认之后,删除冲突部分内容,重新提交
3.4.8 合并提交
在实际开发中,可能一个功能有会N次提交记录,甚至有时候给每次提交取名称都变成一件脑壳疼的问题,并且这种“重复性”的提交如果大家都推送至远端仓库,会导致远端仓库的提交记录密密麻麻,不易梳理。其实我们可以把这些“重复性”的提交合并为一次提交记录再推送至远端仓库。
语法:git rebase -i HEAD~最近几次提交次数
例如, 表示合并最近3次的提交记录:
Git rebase -i HEAD~-3
执行这个命令后会跳到一个vi编辑器
里面的提示有:
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)
保存之后出现下面的内容改成你想提交的概述即可:
[detached HEAD 8c0b26b] 合并了3次提交
Date: Mon May 9 11:22:01 2022 +0800
1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/dev.
保存之后,我们发现提交记录已经被合并了
冲突解决
在 git rebase
过程中,可能会存在冲突,此时就需要解决冲突。
错误提示信息:git rebase -i resumeerror: could not apply ...
。
# 查看冲突
$ git status
# 解决冲突之后,本地提交
$ git add .
# rebase 继续
$ git rebase --continue
3.4.9、开发中分支使用原则与流程
几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离
开来进行重大的Bug修改、开发新的功能,以免影响开发主线。
在开发中,一般有如下分支使用原则与流程:
master(生产) 分支
线上分支,主分支,中小规模项目作为线上运行的应用对应的分支;
develop(开发)分支
是从master创建的分支,一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线
要求,都可以在此版本进行开发,阶段开发完成后,需要是合并到master分支,准备上线。
feature/xxxx 分支
从develop创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的研发任务完成后合并到develop分支。
hotfix/xxxx分支
从master派生的分支,一般作为线上bug修复使用,修复完成后需要合并到master、test、
develop分支。
还有一些其他分支,在此不再详述,例如test分支(用于代码测试)、pre分支(预上线分支)等等。
3.4.10练习:分支操作
###########################创建并切换到dev01分支,在dev01分支提交
# [master]创建分支dev01
git branch dev01
# [master]切换到dev01
git checkout dev01
# [dev01]创建文件file02.txt
略
# [dev01]将修改加入暂存区并提交到仓库,提交记录内容为:add file02 on dev
git add .
git commit -m 'add file02 on dev'
# [dev01]以精简的方式显示提交记录
git-log
###########################切换到master分支,将dev01合并到master分支
# [dev01]切换到master分支
git checkout master
# [master]合并dev01到master分支
git merge dev01
# [master]以精简的方式显示提交记录
git-log
# [master]查看文件变化(目录下也出现了file02.txt)
略
##########################删除dev01分支
# [master]删除dev01分支
git branch -d dev01
# [master]以精简的方式显示提交记录
git-log
ls/ll 查看当前目录
cat 查看文件内容
touch 创建文件
vi vi编辑器(使用vi编辑器是为了方便展示效果,学员可以记事本、editPlus、notPad++等其它编 辑器)
3.1、 Git环境配置
3.1.1 下载与安装
下载地址: https://git-scm.com/download
双击下载的安装文件来安装Git。安装完成后在电脑桌面(也可以是其他目录)点击右键,如果能够看到如下两个菜单则说明Git安装成功。
备注:
Git GUI:Git提供的图形界面工具
Git Bash:Git提供的命令行工具
当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用该用户信息
3.1.2基本配置
-
打开Git Bash
-
设置用户信息
git config --global user.name “yushangxue”
git config --global user.email “你的邮箱@qq.com”
查看配置信息
git config --global user.name
git config --global user.email
3.1.3 常用指令配置别名(可选)
有些常用的指令参数非常多,每次都要输入好多参数,我们可以使用别名。
-
打开用户目录(C:\Users\Administrator),创建
.bashrc
文件
部分windows系统不允许用户创建点号开头的文件,可以打开gitBash,执行 touch ~/.bashrc
-
在 .bashrc 文件中输入如下内容:
#用于输出git提交日志
alias git-log='git log --pretty=oneline --all --graph --abbrev-commit'
#用于输出当前目录所有文件及基本信息
alias ll='ls -al'
-
在用户目录 打开gitBash,执行
source ~/.bashrc
3.2、获取本地仓库
要使用Git对我们的代码进行版本控制,首先需要获得本地仓库
1)在电脑的任意位置创建一个空目录(例如test)作为我们的本地Git仓库
2)进入这个目录中,点击右键打开Git bash窗口
3)执行命令git init
4)如果创建成功后可在文件夹下看到隐藏的.git目录。
3.3、基础操作指令
Git工作目录下对于文件的修改(增加、删除、更新)会存在几个状态,这些修改的状态会随着我们执行Git 的命令而发生变化。
本章节主要讲解如何使用命令来控制这些状态之间的转换:
-
git add (工作区 --> 暂存区)
-
git commit (暂存区 --> 本地仓库)
提出疑问?暂存区是干什么的?
在软件开发中,很多时候要求我们停止手头上的活去处理别的事情,但此时代码写到一半,无法commit到分支/主干。此时,Git提供了一个暂时存储的功能,将代码add到暂存区,然后将其放在安全的位置,等到紧急任务处理完毕之后,在切回来处理手头上的工作。
3.3.0 工作区与暂存区
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
先来看名词解释。
工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的gitdemo
文件夹就是一个工作区:
版本库(Repository)
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
分支和HEAD
的概念我们以后再讲。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
俗话说,实践出真知。现在,我们再练习一遍,先对readme.txt
做个修改,比如加上一行内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
然后,在工作区新增一个LICENSE
文本文件(内容随便写)。
先用git status
查看一下状态:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE
no changes added to commit (use "git add" and/or "git commit -a")
Git非常清楚地告诉我们,readme.txt
被修改了,而LICENSE
还从来没有被添加过,所以它的状态是Untracked
。
现在,使用两次命令git add
,把readme.txt
和LICENSE
都添加后,用git status
再查看一下:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE
modified: readme.txt
现在,暂存区的状态就变成这样了:
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
$ git commit -m "understand how stage works"
[master e43a48b] understand how stage works
2 files changed, 2 insertions(+)
create mode 100644 LICENSE
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
$ git status
On branch master
nothing to commit, working tree clean
现在版本库变成了这样,暂存区就没有任何内容了:
3.3.1、查看修改的状态(status)
作用:查看的修改的状态(暂存区、工作区)
命令形式:git status
3.3.2、添加工作区到暂存区(add)
作用:添加工作区一个或多个文件的修改到暂存区
命令形式:git add 单个文件名|通配符
将所有修改加入暂存区:git add .
3.3.3、提交暂存区到本地仓库(commit)
作用:提交暂存区内容到本地仓库的当前分支
命令形式:git commit -m '注释内容'
3.3.4、查看提交日志(log)
在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的工具是 git log
命令。
最有意思的是 format
,可以定制记录的显示格式。 这样的输出对后期提取分析格外有用——因为你知道输出的格式不会随着 Git 的更新而发生改变:
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
列出了 format
接受的常用格式占位符的写法及其代表的意义。
选项 | 说明 |
---|---|
%H |
提交的完整哈希值 |
%h |
提交的简写哈希值 |
%T |
树的完整哈希值 |
%t |
树的简写哈希值 |
%P |
父提交的完整哈希值 |
%p |
父提交的简写哈希值 |
%an |
作者名字 |
%ae |
作者的电子邮件地址 |
%ad |
作者修订日期(可以用 --date=选项 来定制格式) |
%ar |
作者修订日期,按多久以前的方式显示 |
%cn |
提交者的名字 |
%ce |
提交者的电子邮件地址 |
%cd |
提交日期 |
%cr |
提交日期(距今多长时间) |
%s |
提交说明 |
你一定奇怪 作者 和 提交者 之间究竟有何差别, 其实作者指的是实际作出修改的人,提交者指的是最后将此工作成果提交到仓库的人。 所以,当你为某个项目发布补丁,然后某个核心成员将你的补丁并入项目时,你就是作者,而那个核心成员就是提交者。 我们会在 再详细介绍两者之间的细微差别。
当 oneline
或 format
与另一个 log
选项 --graph
结合使用时尤其有用。 这个选项添加了一些 ASCII 字符串来形象地展示你的分支、合并历史:
$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local
这种输出类型会在我们下一章学完分支与合并以后变得更加有趣。
以上只是简单介绍了一些 git log
命令支持的选项。 列出了我们目前涉及到的和没涉及到的选项,以及它们是如何影响 log 命令的输出的:
选项 | 说明 |
---|---|
-p |
按补丁格式显示每个提交引入的差异。 |
--stat |
显示每次提交的文件修改统计信息。 |
--shortstat |
只显示 --stat 中最后的行数修改添加移除统计。 |
--name-only |
仅在提交信息后显示已修改的文件清单。 |
--name-status |
显示新增、修改、删除的文件清单。 |
--abbrev-commit |
仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 |
--relative-date |
使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 |
--graph |
在日志旁以 ASCII 图形显示分支与合并历史。 |
--pretty |
使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format(用来定义自己的格式)。 |
--oneline |
--pretty=oneline --abbrev-commit 合用的简写。 |
--decorate |
标记会让git log显示每个commit的引用(苹果电脑可能会用到) |
GIT 日志图形化解释
符号解释:
// *表示一个commit, 表示提交是发生在那个分支上的|表示分支前进/表示分叉\表示合入
过程解释:
-
base master: master first commit
-
|/这个符号表示新分支, 可以看见是新增br1: br1-first-commit
-
master前进:master-second-commit
-
master merged into br1
-
master前进:master-third-commit
-
br2前进:br2-first-commit(rebase)
-
br2前进:br2-second-commit(rebase【此commit在rebase后提交】)
3.3.5、版本回退/版本穿梭
文件回退
## 删除文件(如果没有commit的话,是可以回退回来的,因为当前文件并未从本地版本库移除)
git rm 文件名
## 文件恢复
git checkout head 文件名
仓库版本回退
作用:版本切换
命令形式:git reset --hard commitID(版本id)
commitID 可以使用 git-log 或 git log 指令查看
git reflog
# 可以找回被删除的历史提交记录
$ git reflog
8537950 (HEAD -> master) HEAD@{0}: reset: moving to 8537950
bc94e9c HEAD@{1}: reset: moving to bc94e9c
8537950 (HEAD -> master) HEAD@{2}: commit: 5.txt 被删除
bc94e9c HEAD@{3}: reset: moving to bc94e9c
38ca380 HEAD@{4}: commit: 删除1.txt
bc94e9c HEAD@{5}: commit: 第二次提交
d126f4f HEAD@{6}: commit (initial): 提交第一文件1.txt
renwoxing@DESKTOP-9D3GBO0 MINGW64 ~/Desktop/gitdemo (master)
$ git-log
* 8537950 (HEAD -> master) 5.txt 被删除
* bc94e9c 第二次提交
* d126f4f 提交第一文件1.txt
3.3.6、添加文件至忽略列表
一般我们总会有些文件无需纳入Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动
生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以在工作目录
中创建一个名为 .gitignore 的文件(文件名称固定),列出要忽略的文件模式。下面是一个示例(.net 常用的):
.Net 忽略文件
# Build and Object Folders
bin/
obj/
# Nuget packages directory
packages/
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.vspscc
*.vssscc
.builds
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help
UpgradeLog*.XML
# Lightswitch
_Pvt_Extensions
GeneratedArtifacts
*.xap
ModelManifest.xml
# Backup file
*.bak
*.dll
Java 忽略文件
# eclipse
*.pydevproject
.project
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
.factorypath
### IntelliJ IDEA ###
*.iml
*.ipr
*.iws
.idea
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
.nb-gradle/
# java
*.class
# Package Files #
*.war
*.ear
#maven
target/
#gradle
.gradle
build/
gradle/
out/
!gradle/wrapper/gradle-wrapper.jar
.DS_Store
.log
#rebel
rebel.xml
log/
*.log
练习:基础操作
#####################仓库初始化######################
# 创建目录(git_test01)并在目录下打开gitbash
略
# 初始化git仓库
git init
#####################创建文件并提交#####################
# 目录下创建文件 file01.txt
touch ./file01.txt
# 将修改加入暂存区
git add .
# 将修改提交到本地仓库,提交记录内容为:commit 001
git commit -m 'commit 001'
# 查看日志
git log
####################修改文件并提交######################
# 修改file01的内容为:count=1
略
# 将修改加入暂存区
git add .
# # 将修改提交到本地仓库,提交记录内容为:update file01
git commit --m 'update file01'
# 查看日志
git log
# 以精简的方式显示提交记录
git-log
####################将最后一次修改还原##################
# 查看提交记录
git-log
# 找到倒数第2次提交的commitID
略
# 版本回退
git reset commitID --hard
3.4、分支
几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离
开来进行重大的Bug修改、开发新的功能,以免影响开发主线。
3.4.1、查看本地分支
命令:git branch
3.4.2、创建本地分支
命令:git branch 分支名
3.4.4、切换分支(checkout)
命令:git checkout 分支名
我们还可以直接切换到一个不存在的分支(创建并切换)
命令:git checkout -b 分支名
3.4.5、合并分支(merge)
一个分支上的提交可以合并到另一个分支
命令:git merge 分支名称
合并分支前,dev分支与master分支目录情况:
合并两个分支后的目录情况:
再比如说:当前分支是A,执行命令:git merge B,意思就是将B分支上的代码合并至当前分支A。
3.4.6 删除分支
不能删除当前分支,只能删除其他分支
git branch -d b1 删除分支时,需要做各种检查
git branch -D b1 不做任何检查,强制删除 (\慎用)
3.4.7、解决冲突 (难点)
当两个分支上对文件的修改可能会存在冲突(conflict),例如同时修改了同一个文件的同一行,当合并分支后必然出现冲突,这时就需要手动解决冲突,解决冲突步骤如下:
-
处理文件中冲突的地方 (需要开发者人为手动的解决)
-
将解决完冲突的文件加入暂存区(add)
-
提交到仓库(commit)
冲突部分的内容处理如下所示
此时就需要与其他开发者沟通,确认使用哪位开发者修改的内容,确认之后,删除冲突部分内容,重新提交
3.4.8 合并提交
在实际开发中,可能一个功能有会N次提交记录,甚至有时候给每次提交取名称都变成一件脑壳疼的问题,并且这种“重复性”的提交如果大家都推送至远端仓库,会导致远端仓库的提交记录密密麻麻,不易梳理。其实我们可以把这些“重复性”的提交合并为一次提交记录再推送至远端仓库。
语法:git rebase -i HEAD~最近几次提交次数
例如, 表示合并最近3次的提交记录:
Git rebase -i HEAD~-3
执行这个命令后会跳到一个vi编辑器
里面的提示有:
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)
保存之后出现下面的内容改成你想提交的概述即可:
[detached HEAD 8c0b26b] 合并了3次提交
Date: Mon May 9 11:22:01 2022 +0800
1 file changed, 3 insertions(+)
Successfully rebased and updated refs/heads/dev.
保存之后,我们发现提交记录已经被合并了
冲突解决
在 git rebase
过程中,可能会存在冲突,此时就需要解决冲突。
错误提示信息:git rebase -i resumeerror: could not apply ...
。
# 查看冲突
$ git status
# 解决冲突之后,本地提交
$ git add .
# rebase 继续
$ git rebase --continue
3.4.9、开发中分支使用原则与流程
几乎所有的版本控制系统都以某种形式支持分支。 使用分支意味着你可以把你的工作从开发主线上分离
开来进行重大的Bug修改、开发新的功能,以免影响开发主线。
在开发中,一般有如下分支使用原则与流程:
master(生产) 分支
线上分支,主分支,中小规模项目作为线上运行的应用对应的分支;
develop(开发)分支
是从master创建的分支,一般作为开发部门的主要开发分支,如果没有其他并行开发不同期上线
要求,都可以在此版本进行开发,阶段开发完成后,需要是合并到master分支,准备上线。
feature/xxxx 分支
从develop创建的分支,一般是同期并行开发,但不同期上线时创建的分支,分支上的研发任务完成后合并到develop分支。
hotfix/xxxx分支
从master派生的分支,一般作为线上bug修复使用,修复完成后需要合并到master、test、
develop分支。
还有一些其他分支,在此不再详述,例如test分支(用于代码测试)、pre分支(预上线分支)等等。
3.4.10练习:分支操作
###########################创建并切换到dev01分支,在dev01分支提交
# [master]创建分支dev01
git branch dev01
# [master]切换到dev01
git checkout dev01
# [dev01]创建文件file02.txt
略
# [dev01]将修改加入暂存区并提交到仓库,提交记录内容为:add file02 on dev
git add .
git commit -m 'add file02 on dev'
# [dev01]以精简的方式显示提交记录
git-log
###########################切换到master分支,将dev01合并到master分支
# [dev01]切换到master分支
git checkout master
# [master]合并dev01到master分支
git merge dev01
# [master]以精简的方式显示提交记录
git-log
# [master]查看文件变化(目录下也出现了file02.txt)
略
##########################删除dev01分支
# [master]删除dev01分支
git branch -d dev01
# [master]以精简的方式显示提交记录
git-log