//此笔记基于廖雪峰的Git教程
Version 1.0 @2017.8.23 @RoseauHan
请勿用于商业用途
Git是目前世界上最先进的分布式版本控制系统,这是它诞生的故事。
了解更多请参考文末的References,感谢阅读:)
创建版本库
初始化一个Git仓库,使用git init命令。
添加文件到Git仓库,分两步:
- 第一步,使用命令
git add <file>,注意,可反复多次使用,添加多个文件; - 第二步,使用命令
git commit,完成。
时光机穿梭
要随时掌握工作区的状态,使用git status命令。
如果git status告诉你有文件被修改过,用git diff可以查看修改内容。
版本回退
- HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令
git reset --hard commit_id。 - 穿梭前,用
git log可以查看提交历史,以便确定要回退到哪个版本。 - 要重返未来,用
git reflog查看命令历史,以便确定要回到未来的哪个版本。
工作区和暂存区
我们把文件往Git版本库里添加的时候,是分两步执行的:
-
第一步是用
git add把文件添加进去,实际上就是把文件修改添加到暂存区; -
第二步是用
git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
-
git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。
管理修改
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。
第一次修改 -> git add -> 第二次修改 -> git commit
你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,
-
git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
那怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit.
撤销修改
- 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- file。 - 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令
git reset HEAD file
,就回到了场景1,第二步按场景1操作。 - 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。
删除文件
- 命令行删除
git rm file - 确实要从版本库中删除该文件,那就用命令
git rm删掉,并且git commit - 如果删错,
git checkout(用法:git checkout -- file)其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
(一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。)
远程仓库
-
第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。 -
第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容。完成。
添加远程库
要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git;
关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
常见问题
-
1.当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?
这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。
Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
这个警告只会出现一次,后面的操作就不会有任何警告了。
参考Referring:Connecting-to-github-with-ssh -
2.如何解决 failed to push some refs for git?
出现错误的主要原因是github中的README.md文件不在本地代码目录中,可以通过如下命令进行代码合并 [注:pull=fetch+merge]
git pull --rebase origin master
执行上面代码后可以看到本地代码库中多了README.md文件,
此时再执行语句git push -u origin master即可完成代码上传到github。
参考Referring:如何解决 failed to push some refs for git
从远程库克隆
-
要克隆一个仓库,首先必须知道仓库的地址,然后使用
git clone命令克隆。 -
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快.
-
你也许还注意到,GitHub给出的地址不止一个,还可以用https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
-
使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。
分支管理
Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。
创建与合并分支
-
查看分支:
git branch -
创建分支:
git branch <name> -
切换分支:
git checkout <name> -
创建+切换分支:
git checkout -b <name> -
合并某分支到当前分支:
git merge <name> -
删除分支:
git branch -d <name>
解决冲突
- 当出现
Your branch is ahead of 'origin/master' by 1 commit.这种无法自动合并的情况时,就必须首先解决冲突,解决之后,再提交,合并完成。 - 可以先用
cat命令查看冲突,用带参数的git log命令git log --graph --pretty=oneline --abbrev-commit也可看到分支的合并情况。 - 退出
git log的方法: 输入q
分支管理策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
团队合作的分支看起来就像这样
- Git分支十分强大,在团队开发中应该充分应用。合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
Bug分支
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;当手头工作没有完成时,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
-
先把工作现场
git stash一下,然后git checkout name切换分支去修复bug, -
修复后回到原工作分支,
git status发现工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看,工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:- 一是用
git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
- 一是用
- 另一种方式是用
git stash pop,恢复的同时把stash内容也删了再git stash pop,回到工作现场。再用git stash list查看,就看不到任何stash内容了。
- 另一种方式是用
-
你可以多次stash,恢复的时候,先用
git stash list查看,然后恢复指定的stash,用命令:$ git stash apply stash@{0}
小结
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。
Feature分支
开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除
多人协作
多人协作的工作模式通常是这样:
-
首先,可以试图用
git push origin branch-name推送自己的修改; -
如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; -
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用
git push origin branch-name推送就能成功! -
如果
git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name。
小结
-
查看远程库信息,使用
git remote -v; -
本地新建的分支如果不推送到远程,对其他人就是不可见的;
-
从本地推送分支,使用
git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交; -
在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致; -
建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name; -
从远程抓取分支,使用
git pull,如果有冲突,要先处理冲突。
标签管理
-
Git的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。
-
tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。
创建标签
-
命令
git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id :git tag v0.9 6224937 -
可以用
git show <tagname>查看标签信息 -
可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:
$ git tag -a v0.1 -m "version 0.1 released" 3628164 -
git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;
签名采用PGP签名,因此,必须首先安装gpg(GnuPG),如果没有找到gpg,或者没有gpg密钥对,就会报错:gpg: signing failed: secret key not available error: gpg failed to sign the data error: unable to sign the tag
如果报错,请参考GnuPG帮助文档配置Key。 -
命令
git tag可以查看所有标签。
操作标签
-
命令
git push origin <tagname>可以推送一个本地标签; -
命令
git push origin --tags可以推送全部未推送过的本地标签; -
命令
git tag -d <tagname>可以删除一个本地标签; -
命令
git push origin :refs/tags/<tagname>可以删除一个远程标签。
使用GitHub
-
在GitHub上,可以任意Fork开源仓库;
-
自己拥有Fork后的仓库的读写权限;
-
可以推送pull request给官方仓库来贡献代码
自定义git
$ git config --global color.ui true Git会适当地显示不同的颜色
忽略特殊文件
忽略文件的原则是:
- 忽略操作系统自动生成的文件,比如缩略图等;
- 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是-
- 通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
- 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。
忽略某些文件时,需要编写.gitignore:
.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理
参考Referring:[https://github.com/github/gitignore](https://github.com/github/gitignore)
配置别名
-
如果敲
git st就表示git status那就简单多了,当然这种偷懒的办法我们是极力赞成的,实现方法:
$ git config --global alias.你的缩写 原名eg:
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch -
--global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
-
配置Git的时候,加上--global是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
-
每个仓库的Git配置文件都放在.git/config文件中:
别名就在[alias]后面,要删除别名,直接把对应的行删掉即可。
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中;
(配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。)
搭建Git服务器
点击标题直接查看
References
Git - Wikipedia
git - 简明指南
GitHub Help
图解Git
About me
Simple || Practical || Interest
c’est un roseau pensant.
不喜欢标签化却又不得不通过标签介绍自己的一个人。
目前,可以通过email RoseauHan@gmail.com 联系我,也可以通过我的简书个人主页的其他方式联系到我,欢迎关注RoseauHan的instagram主页。









网友评论