以下内容大部分整理自廖雪峰的官方网站,在此记录只是方便自己复习。
初识
初始化一个Git仓库,切换到该目录使用git init命令。
添加文件到Git仓库,分两步:
1.使用命令git add <file>
(注意,可添加多个文件,一次commit所有添加的)
2.使用命令git commit -m “message”
。(在commit 之前用git status 看看准备commit的有哪些)
工作区和版本库:
工作区(Working Directory)就是你在电脑里能看到的目录。
版本库(Repository):工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。

前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的。
时光机穿梭
所有的版本控制系统,只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”。而对于图片、视频这些二进制文件,版本控制系统没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。( Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的 )
文本是有编码的,比如中文有常用的GBK编码,日文有Shift_JIS编码,如果没有历史遗留问题,强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
不要使用Windows自带的记事本编辑任何文本文件。记事本在保存UTF-8编码的文件时会在每个文件开头添加0xefbbbf(十六进制)的字符,因此会带来很多问题,比如明明正确的程序一编译就报语法错误,等等。建议用Notepad代替记事本(Notepad++的默认编码设置为UTF-8 without BOM)
查看修改
用 git status
可查看工作区状态。如果git status告诉你有文件被修改过,用git diff
可以查看修改内容。
管理修改
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD <file>
,就回到了场景1,第二步按场景1操作。
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本控制,不过前提是没有推送到远程库。
当在工作区删了文件后(该文件commit过),此时工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了。一是确实要从版本库中删除该文件,那就用命令git rm filename
删掉,并且git commit
。另一种情况是删错了,因为版本库里还有呢,所以可以用 git checkout -- file
把误删的文件恢复到版本库的最新版本。(git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”)
版本控制
每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作。
git log
查看历史修改信息,可加上–pretty=oneline
看到的一大串类似1094adb…的是commit id(版本号),Git的commit id是一个SHA1计算出来的一个非常大的数字,用十六进制表示。(防止多人在同个版本库里时版本号冲突)
Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交,上一个版本就是HEAD^,上上一个版本就是HEAD^^,往上100个版本写成HEAD~100。
只要命令行窗口还没有被关掉,就可以找到那个想要恢复到的commit id,于是就可以指定回到未来的某个版本。(版本号没必要写全,但也不能只写前一两位,因为Git可能会找到多个)。当你想回到未来某个版本就必须知道其对应的commit id。Git提供了一个命令git reflog
用来记录你的每一次命令。
总结:
· git reset --hard commit_id
可以去到不同版本(注意,cmd控制台中换行符默认是^ , ^ 符号会被当做换行符而被git命令忽略掉,可改用~)
· git log
可以查看提交历史,以便确定要回退到哪个版本。
· git reflog
查看命令历史,以便确定要回到未来的哪个版本
远程仓库
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
为了更方便,可以自己搭建一台运行Git的服务器,也可以用GitHub。只要注册一个GitHub账号,就可以免费获得Git远程仓库。
分支管理
Git鼓励大量使用分支:
查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>
或者git switch <name>
创建+切换分支:git checkout -b <name>
或者git switch -c <name>
合并某分支到当前分支:git merge <name>
(解决冲突)
删除分支:git branch -d <name>
此处建议去廖雪峰官网看看示意图,以便更好理解分支。
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

分支策略:master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;干活都在dev分支上,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
处理bug
1. 修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
2. 当手头工作没有完成时,先把工作现场git stash
一下,然后去修复bug,修复后,再git stash pop
,回到工作现场;
3. 在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>
命令,把bug提交的修改“复制”到当前分支,避免重复劳动。
一般流程
0. 要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git
1. 首先,可以试图用git push origin <branch-name>
推送自己的修改;
2. 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull
试图合并;
3. 如果合并有冲突,则解决冲突,并在本地提交;
4. 没有冲突或者解决掉冲突后,再用git push origin <branch-name>
推送就能成功!
5. 如果git pull
提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。