目录
四、管理文件 1、基本命令 2、版本回退 3、撤销修改 4、删除文件
五、远程仓库 1、SSH加密 2、添加远程库 3、删除远程库 4、从远程库克隆
六、分支管理 1、创建和合并分支 2、解决冲突 3、分支管理
4、Bug分支 5、Feature分支 6、多人协作 7、Rebase
十、自定义Git 1、忽略特殊文件 2、配置别名 3、搭建Git服务器
参考廖雪峰的Git教程 Git Cheat Sheet建议打印备用 官网https://git-scm.com/
Git是目前世界上最先进的分布式版本控制系统。版本控制系统,能记录每次文件的改动。
集中式版本控制系统,版本库是集中存放在中央服务器的,需要联网。SVN修正了CVS的一些稳定性问题,是目前用得最多的集中式版本库控制系统。
分布式版本控制系统,根本没有中央服务器,每个人的电脑上都是一个完整的版本库,不必联网。多人协作时,只需把各自的修改推送给对方。因为每个人的电脑都有完整的版本库,安全性高很多。(通常也有一台充当“中央服务器”的电脑,但仅仅是用来方便“交换”大家的修改)
注意:
所有的版本控制系统,只能跟踪文本文件的改动,比如TXT、网页、程序代码等。而图片、视频、Word文件是二进制文件,没法跟踪文件的变化。
Nodepad++:使用Windows要特别注意,千万不要使用Windows自带的记事本编辑任何文本文件,会在每个文件开头添加0xefbbbf字符,会遇到很多问题。建议下载Nodepad++代替记事本,把Notepad++的默认编码设置为UTF-8 without BOM。
UTF-8编码:文本是有编码的,如果没有历史遗留问题,强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
一、安装
在Windows上使用Git,可从Git官网直接下载安装程序https://git-scm.com/downloads,按默认选项安装。开始菜单“Git”->“Git Bash”,弹出类似命令行窗口如下图,说明Git安装成功。
Git是分布式版本控制系统,每台机器必须自报家门(名字和Email地址)。--global表示你这台机器所有的Git仓库都使用这个配置。在命令行输入:
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
二、工作区和版本库
工作区(Working Directory)指在电脑里能看到的目录。版本库(Repository)指工作区的隐藏目录.git,这个不算工作区。
Git的版本库有stage(或者叫index)暂存区,Git自动创建的第一个分支master,及指向master的指针HEAD。
git add把文件修改添加到暂存区,git commit把暂存区的所有内容提交到当前分支。Git跟踪并管理的是修改,而非文件。每次修改,如果不用git add到暂存区,就不会加入到commit中。
三、创建版本库
版本库又名仓库,可简单理解为一个目录,该目录里所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,在将来某个时刻可以“还原”。
(1)创建一个空目录learngit,有内容的目录也可以。如果使用Windows系统,确保目录名不含中文。
(2)运行git init把这个目录变成Git可以管理的仓库,当前目录下多了.git文件夹(默认隐藏)。
(3)把文件添加到版本库。编写文件,放到learngit或其子目录下。
四、管理文件
1、基本命令
git add readme.txt
告诉Git,把文件修改添加到仓库;
git commit -m "wrote a readme file"
告诉Git,把(多个)文件提交到仓库,-m后面输入的是本次提交说明,最好是有意义的;
git status
获取仓库当前的状态;
Untracked files 有未被跟踪的文件
Changes to be committed 有未提交的文件
nothing to commit, working tree clean 没有被修改的文件
git diff readme.txt
查看具体修改的内容(difference),显示的格式是Unix通用的diff格式。
2、版本回退
git log
查看历史记录,显示从最近到最远的提交日志,以便确定要回退到哪个版本。git log --pretty=oneline使每条记录显示在同一行。git log --pretty=oneline --abbrev-commit使每条记录显示在同一行且简写。
git reset --hard b8094
回退到指定版本,可以是未来的版本。
git reset --hard HEAD^
回退到上一个版本。
git reflog
记录你的每一次命令。如果已经关闭cmd,要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
每提交一个新版本,Git会把它们自动串成一条时间线。Git在内部有个指向当前版本的HEAD指针,回退版本时,Git仅仅是修改HEAD的指向,版本回退速度非常快。
b8094a0...是commit id(版本号),是SHA1计算出来的一个非常大的数字,用十六进制表示。Git是分布式的版本控制系统,多人在同一个版本库里工作时为了避免冲突。版本号写前几位就可以,Git会自动去找。
当前版本HEAD,上一个版本HEAD^,上上一个版本HEAD^^,往上100个版本HEAD~100。cmd控制台中换行符默认是^,输入HEAD^,回车可能出现more?问下一行是否需要再输入,最好使用HEAD~。
3、撤销修改
git checkout -- readme.txt
直接丢弃该文件在工作区的修改;
git reset HEAD readme.txt
把暂存区的修改回退到工作区(unstage),之后可再使用git checkout丢弃工作区的修改。
如果已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退,不过前提是没有推送到远程库。
4、删除文件
通常直接在目录中把没用的文件删了。
git rm test.txt
git commit -m "remove test.txt"
从暂存区删除该文件(如果工作区有也会删除),并将删除提交,即从版本库中删除该文件。
git checkout -- test.txt
如果删错了,把误删的文件恢复到最新版本。会丢失最近一次提交后修改的内容。
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
五、远程仓库
找一台电脑充当服务器的角色,每天24小时开机,其他人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。GitHub是提供Git仓库托管服务的,只要注册一个GitHub账号,就可以免费获得Git远程仓库。
1、SSH加密
本地Git仓库和GitHub仓库之间的传输是通过SSH加密的。GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。
创建SSH Key。打开Shell(Windows下打开Git Bash),运行ssh-keygen -t rsa -C "youremail@example.com",一路回车使用默认值即可,这个Key不是用于军事目的无需设置密码。用户主目录->.ssh目录->id_rsa和id_rsa.pub文件是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
登陆GitHub->Settings->SSH and GPG keys->任意Title,在Key文本框里粘贴id_rsa.pub文件的内容,Add SSH Key,可添加多个Key。
SSH警告:第一次使用Git的clone或push命令连接GitHub时,会得到一个警告,因为Git使用SSH连接,第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器(GitHub的RSA Key的指纹信息),输入yes回车即可。
Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了。
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)? yes
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.
2、添加远程库
在本地和GitHub各创建一个Git仓库,让两个仓库进行远程同步,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作。
创建一个新仓库:登陆GitHub->右上角“New repository”->输入Repository name->Create repository。
在本地的learngit仓库下运行如下命令:
git remote add origin https://github.com/CongYao1993/learngit.git
把一个已有的本地仓库与远程仓库关联,远程库的名字是origin。报错fatal: remote origin already exists.说明本地库已经关联了一个名叫origin的远程库,可以另外起名,使本地库同时与多个远程库互相同步。
git remote -v
查看远程库信息。
git push -u origin master
把本地库的所有内容推送到远程库上,实际上是把当前分支master推送到远程分支master。由于远程库是空的,第一次推送master分支时加上-u参数,把本地的master分支和远程的关联起来,在以后的推送或者拉取时可以简化命令。
git push origin master
把本地master分支的最新修改推送至GitHub。
有没有联网都可以正常工作,当有网络的时候,再把本地提交推送一下就完成了同步。
3、删除远程库
git remote rm origin
删除已有的远程库。
4、从远程库克隆
从零开发,最好的方式是先创建远程库,然后从远程库克隆。
登陆GitHub,创建一个新仓库gitskills,勾选Initialize this repository with a README自动创建一个README.md文件。
git clone git@github.com:CongYao1993/gitskills.git或 ssh
git clone https://github.com/CongYao1993/gitskills.git https
克隆一个本地库。Git支持多种协议,默认git://使用ssh,也可以使用https等其它协议。使用https速度慢,且每次推送都必须输入口令,但某些只开放http端口的公司内部无法使用ssh协议。
六、分支管理
创建一个属于自己的分支,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,既安全又不影响别人工作。Git的分支无论创建、切换和删除,无论版本库大小,都很快,只是修改指针。
1、创建和合并分支
(HEAD指向当前分支,master指向提交点)
每次提交,Git都把它们串成一条时间线,master分支都会向前移动一步。这条时间线是主分支,即master分支,master指向最新提交,HEAD此时指向master。
当创建新的分支dev时,Git新建了一个指针dev,指向master相同的提交,再把HEAD指向dev,表示当前分支在dev上。
现在对工作区的修改和提交就是针对dev分支了,如新提交一次后,dev指针往前移动一步,而master指针不变。
假如在dev上的工作完成了,直接把master指向dev的当前提交就完成了合并。甚至可以删除dev分支,即dev指针。
git checkout -b dev
创建并切换到dev分支,相当于git branch dev和git checkout dev;
git branch
查看当前分支,当前分支前标一个*号;
dev分支的工作完成;
git checkout master
切换回master分支,刚才修改的内容不见了,因为master分支的提交点并没有变;
git merge dev
合并指定分支到当前分支,把dev分支的工作成果合并到master分支上;
这次合并是“快进模式”,直接把master指向dev的当前提交,合并速度非常快;
git branch -d dev
删除dev分支。
2、解决冲突
两个分支分别有新的提交,且提交内容有冲突。此时Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突。
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
git status也可以告诉冲突的文件。
Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容。
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。最后删除feature1分支。
git log --graph --pretty=oneline --abbrev-commit
可以看到分支合并图。
3、分支管理
通常合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。强制禁用该模式,Git就会在merge时生成一个新的commit,从分支历史上就可以看出分支信息。
git merge --no-ff -m "merge with no-ff" dev
合并分支时,--no-ff表示禁用Fast forward。本次合并要创建一个新的commit,加上-m参数。
实际开发中,分支管理的基本原则:master分支是非常稳定的,仅用来发布新版本;干活都在dev分支上,dev分支是不稳定的,某个版本发布时,再把dev分支合并到master上,在master分支发布版本。每个人都有自己的分支,时不时地往dev分支上合并就可以了。
4、Bug分支
每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。
git stash
当前正在dev分支上工作,保存当前工作现场,等之后恢复现场后继续工作。保存后用git status查看工作区就是干净的(除非有没有被Git管理的文件)。
切换到修复bug的分支,创建分支修复bug,提交,切换,合并,删除bug分支。
切换回dev分支。
git stash list
查看stash。
git stash pop
恢复的同时把stash内容删除。
git stash apply
git stash drop
恢复工作现场,删除stash内容。
git stash apply stash@{0}
多次stash,恢复指定stash。
5、Feature分支
每添加一个新功能,新建一个feature分支,开发->合并->删除该feature分支。
新feature分支未合并时,功能取消,需要删除。git branch -d命令未合并的分支不能删除。
git branch -D feature2
强行删除未合并的分支。
6、多人协作
master分支是主分支,要时刻与远程同步;dev分支是开发分支,团队所有成员都需要在上面工作,也需要与远程同步;bug分支只用于在本地修复bug,没必要推到远程;feature分支是否推到远程,取决于你是否和小伙伴合作在上面开发。
git clone git@github.com:CathyYao/gitskills.git。从远程库clone时,默认情况下,只能看到本地的master分支。
git checkout -b dev origin/dev
创建远程origin的dev分支到本地,修改后提交。
git push origin dev
推送dev分支。
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并。
git branch --set-upstream-to=origin/dev dev
设置本地dev分支和远程origin/dev分支的链接,否则git pull提示no tracking information。
git pull
把最新的提交从origin/dev抓下来,在本地合并,如果有冲突则解决冲突,提交。
git push origin dev
合并后推送dev分支。
7、Rebase
git rebase
把本地未push的分叉提交历史整理成直线。使查看历史提交的变化时更容易,因为分叉的提交需要三方对比;缺点是本地的分叉提交已经被修改过了。
七、标签管理
发布一个版本时,通常先在版本库中打一个标签(tag),唯一确定打标签时刻的版本,标签是容易记住的有意义的名字。标签是版本库的一个快照,是指向某个commit的指针,跟分支很像,但是不能移动。
1、创建标签
git tag v1.0
切换到需要打标签的分支上,打一个新标签,默认打在最新提交的commit上;
git tag v0.9 f52c633
为某个commit id打标签;
git tag -a v0.1 -m "version 0.1 released" 1094ad
创建带有说明的标签,-a指定标签名,-m指定说明文字;
git tag
查看所有标签,按字母排序;
git show v1.0
查看标签信息。
2、操作标签
git push origin v1.0
推送某个标签到远程。
git push origin --tags
一次性推送全部尚未推送到远程的本地标签。
git tag -d v0.1
删除本地标签。创建的标签都只存储在本地,不会自动推送到远程,打错的标签可以在本地安全删除。如果标签已经推送到远程,先从本地删除。
git push origin :refs/tags/v1.0
从远程删除标签。
八、使用GitHub
GitHub作为免费的远程仓库,可放个人的开源项目;还是一个开源协作社区,有极其强大的克隆和分支功能,可以互相参与别人的开源项目。
参与一个开源项目:Fork,在自己的账号下克隆了该仓库;从自己的账号clone;才能推送修改;如果想修复bug或新增一个功能,修改后往自己的仓库推送;如果希望官方库接受你的修改,发起pull request。
九、使用码云
码云(https://gitee.com/),国内的Git托管服务。码云提供免费的Git仓库,还集成了代码质量检测、项目演示等功能。对于团队协作开发,码云还提供项目管理、代码托管、文档管理的服务,5人以下小团队免费。
(1)注册账号并登录,上传自己的SSH公钥。右上角用户头像->菜单“设置”->“SSH公钥”,填写标题,把用户主目录下的.ssh/id_rsa.pub文件的内容粘贴进去。
(2)将本地git仓库关联到码云的远程库
创建一个新项目:右上角+->新建仓库->输入仓库名称,最好与本地库保持一致,去掉README前的对号。
git remote add origin https://gitee.com/yaocong1993/learngit.git
在本地库上使用git remote add把它和码云的远程库关联。
十、自定义Git
git config --global color.ui true 让Git显示颜色,让命令输出更醒目
1、忽略特殊文件
有时必须把某些文件放到Git工作目录中,但又不能提交它们。在Git工作区的根目录下创建.gitignore文件,把要忽略的文件名填进去,Git会自动忽略这些文件。
不需要从头写.gitignore文件,GitHub已经准备了各种配置文件,只需要组合一下就可以使用了https://github.com/github/gitignore。忽略的文件包括:操作系统自动生成的文件,如缩略图等;编译生成的中间文件、可执行文件等;带有敏感信息的配置文件,如存放口令的配置文件。
把.gitignore提交到Git就完成了。
如果想添加一个文件到Git,但发现添加不了,原因是这个文件被.gitignore忽略了。git check-ignore -v App.class检查该文件与哪个规则冲突,可以修改规则。也可以用git add -f App.class强制添加到Git。
下面是webpack+vue项目所用的.gitignore,所使用IDE的配置文件,如.idea(WebStrom)、.vscode
node_modules
.idea
.vscode
2、配置别名
git config --global alias.st status
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.unstage 'reset HEAD'
git config --global alias.last 'log -1' // 显示最后一次提交信息
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
--global是针对当前用户起作用的,不加则只针对当前的仓库起作用。
当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中。每个仓库的Git配置文件都放在.git/config中,别名在[alias]后面,要删除别名,直接把对应的行删掉即可。
3、搭建Git服务器
自己搭建一台Git服务器作为私有仓库使用。准备一台运行Linux的机器(Ubuntu或Debian)。
VS Code侧边栏的源代码管理(Source Control),可视化Git工具。可点击commit、push等操作。