Git是一种版本标准化工具,是目前最受欢迎的团体协作工具,通过Git我们可以代码的历史版本进行有效的存储,数据发生异常时也能及时恢复,也可以在不修改运行时程序源代码的情况下,进行分支开发,Git也支持跨团队协作等等。

Git基本结构

使用Git,一定要先了解Git的基本结构如下图所示。

Git基本操作

使用git init 创建一个本地Git仓库,初始化成功后会出现.git隐藏文件夹

git使用 用户名 和 email来生成签名区分不同用户

  • 使用git config设置签名的生效范文为本地仓库,签名存储位置为.git/config文件

  • 使用git config -‌-global设置签名生效范围为当前用户登录的操作系统 ,签名存储位置为~/.gitconfig文件

#项目范围
git config   user.name <用户名>
#系统范围
git config --global  user.name <用户邮箱>

最佳实践

使用git status去查看文件从工作区提交到本地库,工作区和暂存区的状态。

在空目录下使用git status控制台会显示以下内容

On branch master  #当前工作区位于主分支

No commits yet    #本地库未接收到任何提交的数据

Nothing to commit #暂存区未接受到任何提交的数据

在当前目录下创建test.txt 输入git status 会提示

On branch master	

No commits yet		

Untracked files:	#发现未被追踪的文件  test.txt 此时test.txt颜色为红
  (use "git add <file>..." to include in what will be committed)
	test.txt

nothing added to commit but untracked files present  #暂存区区未接收到任何提交但是存在未被追踪的数据

使用git add test.txt 将数据提交到暂存区,然后输入 git status 会显示

On branch master	

No commits yet	

Changes to be committed:		#暂存区接收到新提交的文件test.txt
  (use "git rm --cached <file>..." to unstage)
		new file: test.txt		#此时test.txt颜色为绿

如果想要将文件从暂存区删除可以使用 git rm -‌-cached <文件名>

使用git commit -m “<本次提交的注释>” 将暂存区里面的数据提交到本地库

提交完毕后控制台会显示以下信息

[matser (root-commit) 7eee2e4]<本次提交的注释> #第一次提交(根提交)
 1 file changed, 3 insertions(+) #一个文件被修改 新增3行数据
 create mode 100644 test.txt

本地库提交完成后 输入 git status 控制台显示以下信息

On branch master	

nothing to commit.working tree is clean	#暂存区没有接收到任何提交的数据 工作树是干净的

修改test.txt 输入git status 控制台会显示以下内容

On branch master	

No commits yet		

Changes not staged for commit:	#修改文件违背提交
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)

	modified: test.txt      #test.txt颜色为红

No changes added to commit	#暂存区没有收到提交的修改数据

输入git add <文件名> 将数据提交到暂存区 使用git commit -m “<本次提交的注释>” 将数据提交到本地库,控制台会显示以下内容

[matser 60d2eac]<本次提交的注释>
 1 file changed, 3 insertions(+) #一个文件被修改 新增3行数据

Git的日志操作

日志查看

使用git命令查看日志

使用git log 查看每次提交到本地库的日志,只显示根提交到Head头指针之间的历史

commit 744e2e479a6a15e305a9ce9ff11608d320ff0bb8 #hash值
Author: 用户名 <邮箱>
Date: Fri May 11 14:48:14 2019 +08080
	<本次提交的注释>

使用git log -‌-pretty=oneline去将信息一行显示

744e2e479a6a15e305a9ce9ff11608d320ff0bb8 (HEAD -> master) <本次提交的注释>	

使用git log -‌-oneline显示简要hash值并以一行显示

744e2e (HEAD -> nmasert) <本次提交的注释>

使用git reflog查看全部历史

64011af (HEAD -> master) HEAD@{0}:commit: <本次提交的注释>
526eb78 HEAD@{1}: commit: <本次提交的注释>

定位历史版本

Git可以通过移动头指针来恢复到某个历史版本。

  • git reset -‌-hard <简要hash> 将头指针定位到某个历史版本

    HEAD is now at 526eb78 <本次提交的注释>
    
  • 使用git reset -‌-hard HEAD^后退 ,一个^表示后退一步,n个表示后退n步

  • 使用git reset -‌-hard HEAD~n后退,n代表n步

除了-‌-hard还可以使用soft、mixed两个参数,他们的具体区别如下

参数指针移动位置结果
-‌-soft只移动本地库指针文件内容不变,暂存区未commit
-‌-mixed移动本地库和暂存区指针本地文件不变,工作区未add
-‌-hard移动本地库、暂存区、工作区全部指针本地库、暂存区、工作区全部移动

文件误删恢复

前提是: 文件存在的状态提交到了本地库,如果没有则无法找回。

文件误删情况情况分以下两种

  • 本地文件被删除同时已经提交到本地库 ,可以使用git reflog查看历史版本,并使用git reset -‌-hard <简 要hash>来恢复文件

  • 如果工作区文件已删除并添加到暂存区,但是没有提交到本地库,可以使用git reset -‌-head HEAD来恢复文件

差异化比较

使用git diff 来比较两个历史版本之间的区别

#对比两个历史版本
git diff <简要hash> <简要hash>

#对比本地文件和历史版本
git diff <简要hash> <文件名>

#对比本地文件和上一个版本
git diff HEAD^ test.txt

#对比本地全部文件和历史版本
git diff <简要hash>

#对比暂存区和本地文件
git diff <文件名>

Git分支操作

基本操作

使用git branch -v查看自己当前在哪个分支

使用git branch<分支名>去创建一个分支

使用git checkout <分支名>去切换到某个分支

合并分支需要先切换到被合并的分支,然后使用git merge进行分支合并

冲突处理

注意git不能帮助人们去决定使用哪个修改,所以需要人为干涉。

当两个分支同时修改同一行的时候,合并分支就会产生冲突,此时合并分支控制台会显示以下内容

Auto-merging test.txt
CONFLICT (content):Merage conflict in test.txt
Automatic merge failed;fix conflicts and then commit the result

并且目前所在的分支是(master | hot_fix),这种情况会自动进入到合并分支的操作模式

此时查看产生冲突的文件

<<<<<<< HEAD          
edit by hot_fix
=======                 这行以上内容属于当前分支,以下内容输入合并分支内容
edit by master
>>>>>>> master

输入git status控制台显示

On branch hot_fix
You have unmerged paths.
	(fix conflicts and run "git commit")
	(use "git merge --abort" to abort merge)
    
Unmerged paths:
	(use "git add <file>.." to mark resolution)
    both modified: test.txt

当人为修改好之后,使用git add添加到暂存区,控制台提示

All conflicts fixed but you are still merging
	(use "git commit" to conclude merge)

Changes to be committed:
	modified: test.txt

根据提示,输入git commit -m “<本次提交的注释>” 将分支进行合并,注意不要加文件名

Git本地库和远程库的操作

远程仓库设置

在本地库向远程库同步数据之前,本地库要知道远程库的位置,设置远程仓库有两种形式

  • https
    使用git remote add origin <远程库https连接>的形式来设置远程库

  • ssh
    cd ~ 切换到家目录,ssh -keygen -t rsa -C 邮箱生成key,此时本地会产生.ssh隐藏文件夹,.ssh文件夹里面有一个id_rsa.pub文件,将id_rsa.pub文件内容复制下来。
    在Github Web页面 —> 点击用户头像 —> Setting —>SSH and GPGkeys —> New SSH key —> 将复制的内容粘贴到key里面 —> Add SSH key 。
    git remote add origin_ssh <远程库ssh连接地址>。

然后使用git push origin master将本地master分支上的内容同步到远程仓库

使用git remote -v查看远程仓库的相关信息

团队内操作

A正在开发某一个项目,B想要一起开发。B要进行以下操作

数据同步

那么B需要将A远程库的数据克隆下来

使用git clone <远程仓库https连接地址>克隆到本地

克隆成功后发现本地文件多了一个.git的文件夹

输入git remote -v发现远程仓库的别名已经设置为其来源库的https连接地址

所以git clone完成了三步操作

  • 将远程库的数据下载到本地
  • 初始化本地库
  • 设置远程库的连接地址

上传本地数据

如果B想将自己的修改上传到A的远程仓库,必须加入A的团队

邀请的过程(GitHub)

仓库Setting —> Collaborators —>输入另外一个人的Github账号 —> Add collaborator

然后copy invite link将连接发送给B

B打开链接后,同意邀请即可加入团队

此时B输入git push origin master 即可将本地的master分支同步到A的远程仓库

本地数据同步更新

B将自己修改的内容上传之后,A想要将B更新的内容同步到本地

可以使用git pull命令

git pull命令等于git fetch 和 gti merge

如果不使用git pull origin master,使用git fetch origin master

会将远程库的东西下载到本地并保存为origin/master分支

然后使用git merge origin/master合并分支即可

需要注意的是,如果两个人都修改了同样的位置并都执行了 git push origin master,后推送的会出现推送失败的情况,如果想要推送必须要先执行git pull origin master同步到本地解决冲突后才可以推送。

跨团队操作

如果C想要协助A和B开发但是C属于另外一个公司,那么C需要先将A和B公司的远程库fork下来

然后使用git clone origin <远程仓库https链接> 然后修改完毕之后push origin master

C如果想将自己的远程库的数据提交给A和B公司,那么C需要发布Pull Request请求



在GitHub仓库界面 ---> Pull Request ---> Create pull request ---> 输入消息内容 --->commit

A在在GitHub仓库界面 —> Pull Request —> Files changed 可以查看修改的文件内容 —> Merge pull request合并分支

Commit规范

Commit 提交描述

docs(changelog): update change log to beta.5 

其中:
 docs 则对应修改的类型
 changelog 则是影响的范围
 subject 则是对应做的事件

对应的类型有

  • build:影响构建系统或外部依赖关系的更改(示例范围:gulp,broccoli,npm)
  • ci:更改我们的持续集成文件和脚本(示例范围:Travis,Circle,BrowserStack,SauceLabs)
  • docs:仅文档更改
  • feat:一个新功能
  • fix:修复错误
  • perf:改进性能的代码更改
  • refactor:代码更改,既不修复错误也不添加功能
  • style:不影响代码含义的变化(空白,格式化,缺少分号等)
  • test:添加缺失测试或更正现有测试