Git学习记录

Git学习记录

版本控制的演变

VCS之前的方式:
1、用目录拷贝区别不同版本
2、公共文件容易被覆盖
3、成员沟通成本高,代码继承效率低下

集中式VCS(有中心化服务器):
1、有集中的版本管理服务器
2、具备文件版本管理和分支管理能力
3、继承效率明显提高
4、客户端必须时刻和服务器相连

缺点在于,每个客户端需要和服务端相连接,历史版本在服务端,客户端通常没有所有的历史版本。

分布式VCS
1、服务端和客户端都有完整的版本库
2、脱离服务端、客户端照样可以管理版本
3、历史版本查看无需访问服务器,较集中式VCS更高效率

Git的特点
1、最优的存储能力(林纳斯是内核专家)
2、非凡的性能 (林纳斯是内核专家)
3、开源
4、很容易备份
5、支持离线操作
6、很容易定制工作流程

Git的入门

安装步骤:
Git官网的安装说明

配置入门

配置user.name和user.email
git config –global user.name “ascend”
git config –global user.email “[email protected]

name、email信息的目的
1、记录谁变更的
2、codereview的时候,评审人员支出问题,git的web管控系统自动发送邮件

关于 local、global、system的区别
local:只对某个仓库有效
global:对当前用户所有仓库有效 (工作最常用)
system对系统所有登录用户有效

显示config的配置,加 –list
git config –list –local
git config –list –global
git config –list –system

建Git仓库

两种场景:
1、把已有的项目代码纳入Git管理,进入到项目代码所在的文件夹,git init 即可
2、新建一个项目直接使用Git管理,进入某个文件夹
git init your_project #会在当前路径下创建和项目名称同名的文件夹
cd your_project

在仓库中添加新的文件,需要先执行,git add 命令,然后才能执行 commit操作,而add 之后的文件将会进入到暂存区。下面就通过4次提交,来认识工作区和暂存区和理解Git的工作方式。

将文件存放到暂存区,然后统一提交

6、文件重命名

重命名文件方法一:
1、在文件系统重命名(例如mv)
2、git add new_filename
3、git rm old_filename

重命名文件方法二(推荐):
git mv old_filename new_filename

7、通过git log查看版本演变历史

1、git log 直接输出最近的变更
2、–oneline 每次变更只显示一行,看起来更简洁
3、–nx 查看最近x次,只显示一行
4、–graph 带图形的查看log,如果有多个分支查看时会很方便
5、–all 所有分支

此外便于测试,git checkout -b temp 7bdb99a31f91264373,可以通过某次提交的hash创建一个分支

8、图形化界面查看版本历史

通过 gitk实现,可以通过view可以自定义图形化界面,以及新建tag等等很多事情

9、关于 .git 文件夹的探秘

HEAD 文件,git仓库正在工作的分支
config 文件,记录了本地仓库相关的配置信息,例如local用户的user信息,可以直接边界
refs 文件夹,下面有tags(标签、里程碑)和heads 文件夹,heads下的文件内容是不同分支的当前指针(commitId),tags同理
objects 文件夹,子文件夹名和子文件夹下的子文件可以组成一个hash,类似于桶存放各个commit提交的内容

git的对象主要是 commit、tree、blob 这三类,当一个文件内容相同git就认为是一个blob

注意,在git中一个短Hash头可以标志唯一性即可(测试貌似最小2字节),如果不能代表唯一则需要输入更长的Hash值

10、commit、tree、和blob三个对象之间的关系

commit:每一次变更,记录着当时整个文件夹在那次提交时的状态
tree:文件夹
blob:文件(和文件内容有关,相同文件内容不同文件视为一个blob)

git cat-file -p hash 获取对象内容
git cat-file -t hash 获取对象类型

12、分离头指针

detached HEAD,本质上就是工作在 没有分支的状态下,如果在这种状态做了变更然后切换到其他分 支会丢失变更内容。

13、HEAD和branch的进一步理解

HEAD不仅仅可以指向某一个分支,还可以指向某个commit(处于分离头指针状态),通过 git checkout -b … 可以创建一个新的分支。

HEAD 标识符可以用于指代当前分支( 分离头指针 )最新的提交,例如下面:
git diff HEAD HEAD^
查看当前版本和上一版本的差异,如果是上上版本则 HEAD^^或者HEAD~2

14、删除不需要的分支

git branch -d branchname
-d 和 -D 的区别?删除一个没有被merge的分支需要使用-D,在不明确的时候使用-d

15,16、怎么修改commit和message

如果是修改最近的一次commit的message,使用 git commit –amend。
如果不是修改最新commit,则需要使用 git rebase 即变基操作。使用 git rebase -i parentHash 在出现的文件中对要更改的提交选择reword,然后保存退出,再第二次出现的文件中,输入变更的信息。

Warning:
这样变更只针对于在自己的分支上操作,如果已经提交这样会比较给其他人带来麻烦
message信息是commit的一个属性,修改message之后,commit的Hash也会随之改变,该commit后面所有的Hash都会改变。

17、怎样把连续的多个commit整理成1个

仍然使用变基操作,git rebase -i parentHash,在出现的文件中,选择 s,然后保存退出,在第二次出现的文件中可以输入本次merge的信息。

18、怎样把间隔的几个commit整理成1个

依然使用,git rebase -i parentHash,可是如果想要将第一个commit和后面的合并怎么办呢?新打开的文件中并没有第一个commit的hash,可以直接在文件中写上第一个commit的hash,然后将需要合并的commit编辑后让他们挨在一起,pick改为s。

注意,如果变基操作修改了第一个commit,那么不同分支会分裂出两颗树。

19,20、工作区、暂存区和HEAD所含文件的差异

git diff 默认展示了工作区和暂存区的差异
— cached 暂存区和HEAD版本的差异
— filenames 可以指定多个文件,只看指定文件

– 表示被删除了
+ 表示添加的
工作区:当前的文件
暂存区:已经 add 的文件
HEAD:本分支指向的最新的版本

21,22,23、暂存区的恢复

恢复暂存区和HEAD一样 :git reset HEAD
让工作区的文件恢复为和暂存区一样:git checkout
— filenames 可以指定恢复哪些文件

24、取消最近的几次提交

git reset –hard hash
注意,当前工作区和暂存区已经更改但是为提交的内容也会被重置

25、查看不同提交的指定文件的差异

git diff branch1 branch2:查看两个分支的差异
— filenames 指定哪些文件的差异

git diff hash1 hash2:查看两个commit的差异(可以是不同branch的)
— filenames 指定哪些文件的差异

26、正确删除文件的方法

git rm filename

27、开发中加塞紧急任务处理

假定,暂存区有内容但是无法提交,本地也有修改。此时新的紧急任务需要加塞处理,怎么办呢?

yt:注意,工作区和暂存区的内容是全局存储的,如果切换分支,修改会体现在新分支。

通过 stash 将当前工作内容暂时存放起来。

git stash:暂存当前工作内容(会恢复到HEAD状态)
git stash list:查看暂存列表,先进后出
git stash pop:恢复,stash列表内容中该stash被剔除
git stash apply:恢复,但是stash列表内容还在,还可以反复使用

28、如何指定不需要git管理的文件

通过 .gitignore 文件指定,这是各个语言的常用.gitignore

29、如何将Git仓库备份到本地

常用的传输协议

直观区别:哑协议传输进度不可见;智能协议传输可见
传输速度:智能协议相对更快

git clone –bare:克隆一个不带工作区的裸仓库
git remote -v:查看远端仓库
git remote add:设置远端仓库

个人关于git远端仓库的理解,其实远端仓库也并不是一个特殊的仓库(bare不算特殊),任何一个普通的git仓库都可以作为远端存在,在团队开发中为了协同方便,通共用一个仓库作为远端仓库。

30,31,32 配置github公私钥

1、如果没有公私钥则先按照git的说明创建公私钥
2、在github输入公钥,其好处在于每次push可以不必再输入密码,通过公私钥验证身份

33、本地仓库同步到GitHub

在同步到远端前,先执行一下 git pull ,这个操作实际包含了 fetch 和 merge 两个操作。

可以看到,远端的github和本地的master分支出现了不同,他们是两颗独立的树,如果push是会报错的。

git branch: 查看分支
-v :显示更多信息
-a:显示远端分支

通过 git merge github/master 进行合并会报错,因为这是两个不相关的树。
使用 git merge –allow-unrelated-histories github/master

34、不同人修改了不同文件如何处理

多人维护同一个项目时,如果在上一次更新后别人又push了,本地仓库不是最新的,则需要先pull,或者fetch+merge,如果互相修改的都是不同的文件,那么merge是很顺利。

35、不同人修改了同文件的不同区域如何处理

36、不同人修改了同文件的同一区域如何处理

同一文件被其他人修改并提交之后,本地在pull下来会发生冲突,先解决文件冲突内容,再重新提交,注意不要随便删除别人的内容。

37、同时变更了文件名和文件内容如何处理

git pull 会自动修改本地文件名,本地文件的改变仍然保留。

38、同一文件改成了不同文件名如何处理

git会提示冲突,并列出两个文件(双方修改的文件名),然后用户手动选择删除留下一个再提交。

39、集成分支注意事项

1、禁止 push -f,这个命令可以使得之前的commit消失
2、公共分支严禁在本地做变基操作

40、github为什么会火

许多开源项目受到权限问题,以及其他一些低效率事情困扰。即使有SVN,与开源项目合作通常也需要获得项目管理员的许可才能fork项目的一个分支,否则便无法编辑代码。

git引入fork概念,使得开源项目合作更容易。但是这依然无法帮助别人寻找开源项目,很多优秀资源无法被共享,github就诞生了。

github的愿景在于使协作和编写软件更容易

41,42、Github核心功能和如何搜索

核心功能:git官方说明

github高级搜索
以搜索git学习资料为例,输入“git 最好 学习 资料”,直接搜索的话出来的结果寥寥无几,因为github是依据名称和描述来进行搜索的。
但如果输入“git 最好 学习 资料 in:readme”进行搜索,出来的结果就多了很多,结果质量也高了很多,此外还可以依据star进行筛选,输入 starts:>1000 则筛选大于1000 start的仓库。

此外还可依据代码内容搜索代码片段,例如“最好 filename:index.php”,搜索index.php文件中包含“最好”关键字的文件

如果想要在github建立一个博客,试试输入“blog easily start in:readme stars:>5000”搜索一个教程。

github官方搜索说明文档

48、怎样选择适合自己团队的工作流

1、团队人员组成
2、研发设计能力
3、输出产品的特征
4、项目难易程度

主干开发

GitFlow工作流

48、国内互联网企业为什么喜欢Gitlab

1、提供开源社区版本,由公司自己搭建,甚至二次开发
2、帮助Gitlab的维护人员很多,文化很好,不停的有新功能出现
3、Gitlab的CI(持续集成)是一个特色

49、Gitlab有哪些核心功能

在官网可以看到功能介绍

补充内容

关于git submodule,这篇文章解释得不错

1、submodule的子仓库在commit之后,需要在主仓库也提交更新,但是主仓库提交的是子仓库的 git commitId,如果此时主仓库被推送到远端分支,子仓库未推送,那么在别人 pull 主仓库之后,执行 git submodule update 将会导致报错,因为远端的主仓库记录的 git commitId 大于子仓库的 commitId。
2、由于submodule记录的是commitId,所以 git submodule update 之后会进入分离头指针的状态,因为子仓库是以commitId来更新的
//3、如果使用git submodule 在 git submodule add 之后还需要 git submodule init 否则 ./git/config 文件不会记录子仓库的信息
4、如果一个子仓库被不同的项目使用了,例如A项目在更新了子仓库源码之后提交了,项目B此时无法通过 git submodule update 更新子仓库,因为项目B并没有记录子仓库最新的commitId,一个简单的办法是使用
git submodule foreach git checkout master[指定分支]
git submodule foreach git pull
此处的git submodule foreach 其实就是进入到各个目录执行一遍后面的命令,后面放ls 都可以,就像是一个脚本助手一样,当项目B的子仓库更新完毕之后,执行 git status 会提示子仓库有改动,因为目前子仓库的commitId已经大于主项目记录的子仓库commidId了,在项目B进行提交即可。

搜索一个commitId在哪些分支
git branch -r –contains commitId

删除暂存区的内容
git rm --cached readme.txt

发表评论

邮箱地址不会被公开。 必填项已用*标注