「Tools」:Git and GitHub
这篇文章具体讲述了Git工具的基本本地库操作和与远程库交互的基本操作,包括使用GitHub进行团队外的协作开发。
Git
Git简介
Git历史:
Linux的代码管理:
1991 Linus本人手动合并代码
2002 使用BitKeeper商业软件,授予Linux社区免费使用版本控制
2005 Linus自己用C语言开发了一个分布式版本控制系统:Git
Linus: Talk is cheap, show me the code.
2008 Github上线
Git的优势:
大部分操作在本地完成,不需要联网。
完整性保证:每次提交进行哈希。
尽可能添加数据而不是删除/修改数据,版本都在。
分支操作快捷流畅,以快照的形式。
与Linux命令全面兼容。
Git的结构
Git和代码托管中心
代码托管中心的任务:维护远程库
局域网环境:搭建GitLab作为代码托管中心
外网环境:可以用GitHub和码云作为代码托管中心
本地库和远程库的交互
团队内:
团队外:
fork:复制一份属于自己的远程库
开发新的内容后向库的拥有者 pull request拉取请求,原拥有者可以审核,审核通过后执行merge操作合并到自己的远程库的分支上。
Git命令行基本操作
本地库初始化
初始化本地库
git init
.git文件存放的是本地库相关的子目录和文件,不要删除和随意修改。
删除本地git库
也就是删除本地的.git
文件
- 删除本地库:
rm -rf .git
本地库设置签名
形式:
用户名:
Email:
作用:区分不同开发人员的身份
注:这里设置的签名与远程代码托管中心没有关系。
命令:
项目级别:设置签名仅在本地库起效(如果既有项目级别和用户级别的签名,按照项目级别为准)
设置用户名命令:
git config user.name ***
设置用户邮箱:
git config user.email *****@outlook.com
该信息保存在.git/config文件中。
用户级别:设置签名在当前操作系统的用户范围
设置用户名命令:
git config --global user.name ***
设置用户邮箱命令:
git config --global user.email ****
该消息保存在系统文件~/.gitconfig文件
查看状态
查看工作区、暂存区状态。
git status
本地库版本信息查看
HEAD: 指针,表示当前版本的位置。
显示版本:
完整的版本信息记录(包括完整版本哈希值、作者、提交时间)
git log
(空格向下翻页;b 向上翻页; q退出显示)一行只显示一个版本,简洁版。
git log --pretty=oneline
一行也只显示一个版本,终极简洁版,哈希值也只显示前面的一部分(当作该版本的局部索引)。
git log --oneline
git reflog
:跟踪本地库的历史更新,可以看到HEAD之后(“未来“)的版本。HEAD@{i}:i表示HEAD指针移动到该版本需要后退的步数。
工作区操作:添加/修改/提交/删除
对于这些命令,其实在使用git status
时,都会有相关提示。
提交到暂存区(增加、修改、删除):
git add <filename>
撤销工作区的修改(discard changes in working directory)
git checkout -- <file>
暂存区操作:添加/修改/提交/删除
对于这些命令,其实在使用git status
时,都会有相关提示。
添加/修改:将工作区的文件添加到暂存区(/或更新暂存区的文件)。
git add <filename>
删除:将文件从暂存区删除
git rm --cached <filename>
提交:将暂存区的文件提交到本地库。(输入提交信息)
git commit -m <message> [filename]
修改后的提交:提交修改后的文件至本地库(已在暂存区有旧版本),同时更新暂存区和本地库。
git commit -m <message> [filename]
修改commit 注释
git commit --amend
版本前进/后退
本质是HEAD指针的移动。
基于索引操作:版本可以后退和前进。(索引就是reflog形式下的局部哈希值)
git reset --hard [局部索引值]
使用
^
: 版本只能往后退 。(基于reflog形式下的步数)git reset --hard HEAD^^
(后退两步)使用
~n
:版本往后退n步。git reset --hard HEAD~3
版本前进/后退reset命令的参数对比:
--soft
仅仅在本地库移动HEAD指针。
如下图,显得暂存区和工作区版本比本地库前进了一步。
--mixed
在本地库移动HEAD指针
并重置暂存区,暂存区和本地库一致。
如下图,显得工作区版本比本地库和暂存区版本前进了一步。
--hard
- 在本地库移动HEAD指针
- 重置暂存区
- 重置工作区
删除文件后找回
前提:删除前,文件存在的状态提交到了本地库。
操作:
删除的操作已经提交到本地库
删除操作:
1
2
3rm a.txt
git add a.txt
git commit -m "delete a.txt" a.txtgit reset --hard [历史版本指针位置]
删除操作未提交到本地库
删除操作:
1
2
3
4
5//工作区删除
rm a.txt
//缓存区也删除
rm a.txt
git add a.txtgit reset --hard HEAD
比较差异
工作区文件和暂存区文件比较
git diff [filename]
暂存区和本地库内容比较
git diff --cached
工作区文件和本地库文件比较,指针可以使用
HEAD^
git diff [指针] [filename]
可以不加文件名,即比较全部文件。
任意版本之间的内容比较:
显示两次差异文件
git diff 版本1hash/指针 版本2hash/指针 --stat
具体显示差异文件
git diff hash1/指针 hash2/指针 filename
分支管理
分支
分支:版本控制过程中,使用多条线同时推进多个任务。
master: 主版本分支/部署到服务器运行的分支。
feature_ :开发其他功能的分支。
hot_fix: 热修复,bug修复分支。
分支的好处:
- 并行:同时并行推进多个功能开发。
- 独立:各个分支在开发过程中,如果有个分支开发失败,不会影响其他分支。
分支操作:创建/查看/切换/合并
创建分支
git branch <branch name>
删除分支
git branch -d <branch name>
删除远程分支:
- 查看远程分支:
git branch -r
- 删除本地的远程跟踪分支:
git branch -r -d origin/branch-name
- 删除真正的远程分支:
git push origin : branch-name
- 查看远程分支:
查看分支
git branch -v
切换分支
git checkout [branch name]
合并分支
切换到接受修改的分支(如master)
git checkout [合并到的主分支]
执行merge合并操作
git merge [有修改的分支]
解决合并分支后产生的冲突
冲突的表现,显示到有冲突的文件:
冲突解决:
删除文件中的特殊符号
协商再编辑文件
添加新文件
git add [filename]
提交(注意:此时的提交不能带文件名)
git commit -m "message"
rebase:整理分支
- rebase 操作可以把本地未push的分叉提交历史 整理成直线。
- rebase的目的:在查看历史提交的变化时更容易。
Git 基本原理
哈希算法
特点:
- 得到的加密密文长度相同。
- 算法确定,输入确定后,输出一定确定。
- 输入数据发生一点点变化,输出的变化会很大。
- Git底层采用SHA-1算法。
哈希算法保证了Git的数据完整性。
Git保存版本的机制
集中式版本控制工具(如SVN):保存的信息是每个基本文件和每个文件随时间逐步累积的差异。
Git是分布式的版本控制工具。
Git把数据看作是文件系统的快照(可以理解为当前内存版本的文件的索引),每次提交更新时Git对当前内存的全部文件制作一个快照并保存这个快照的索引。如果文件没有修改,Git不会重新存储该文件,只是保留一个连接指向之前存储的文件。
Git的提交对象:
上图中,每个文件都有一个哈希值/索引,提交时新建一个树结点,其中包含指向每个文件的指针/索引,提交的对象包括该树结点的指针/哈希值。
Git版本对象链条:
所以:
Git 分支的创建:等于新建一个指向版本的指针。
Git分支的切换:改变HEAD指针所指的指针。
Git分支版本的移动:分支指针的移动。
GitHub
基本交互
创建/查看远程库地址别名
在GitHub创建远程库后
在本地添加远程库地址别名
git remote add [别名] [https/ssh 地址]
git remote add orgin https://...
查看当前所有远程库地址别名
git remote -v
移除远程库
git remote remove [别名]
本地库内容推送到远程库
前提:本地库已添加远程库地址别名。
在本地将本地库推送到远程分支
git push [别名] [分支名]
git push origin master
将远程库克隆到本地库
git clone https/ssh_address
- 效果:完整把远程库下载到本地;添加origin作为远程库地址别名;初始化本地库(含有.git文件)
团队内协作
团队成员邀请
项目创建者在项目”Setting”-“Callaborators”里邀请成员。
拉取:同步本地库
在本地pull操作同步本地库与远程库相同。
fetch:查看远程库分支,可以切换至远程库分支,查看远程库分支的文件具体内容,决定是否合并。
git fetch [远程库地址别名] [远程分支名]
切换至远程库分支
git checkout orgin/master
merge:(切换至本地库master分支),合并远程库分支。
git merge [远程库地址别名]/[远程分支名]
pull = fetch + merge
git pull [远程库地址别名] [远程分支名]
注:如果是简单的修改,可以直接pull拉取,如果不确定远程库修改内容,可以先fetch后再合并分支。
本地拉取与远程库冲突
- 冲突发生原因:不是基于GitHub远程库的最新版进行修改,就不能push,在修改之前必须pull。
- pull拉取下来后如果进入冲突状态,就按照“分支冲突解决办法”
跨团队协作
fork操作:复制一份远程库。
团队外的人,在项目节目点fork,即可fork一份远程库,该远程库的来源是创建该库的开发者,而fork出的远程库的所有者是执行fork操作的人。
clone操作:下载到本地库。
push操作:本地修改,推送至远程库。
pull request 请求:在远程库(代码托管中心GitHub)执行pull request请求,请求合并该修改到原远程库。
(原远程库所有者)审核操作:确认是否合并。
SSH登陆
在当前用户的根目录,生产.ssh密钥目录
ssh-keygen -t rsa -C email@address
将
.ssh/id_rsa.pub
文件的内容复制到GitHub新建ssh密钥的窗口下。创建ssh远程地址别名
git remote add origin ssh_address
Git仓库和SSH-key关联
ssh-add "id_rsa address
Git工作流
待补充[1]
Gitlab服务器搭建
待补充[2]
Reference
- Git工作流待补充
- Gitlab服务器搭建
「Tools」:Git and GitHub