本文整理廖雪峰老师的Git教程,边学习,边分享给大家
Git基础
集中式和分布式的区别是:
你的本地是否有完整的版本库历史!
假设SVN服务器没了,那你丢掉了所有历史信息,因为你的本地只有当前版本以及部分历史信息。
假设GitHub服务器没了,你不会丢掉任何git历史信息,因为你的本地有完整的版本库信息。你可以把本地的git库重新上传到另外的git服务商。
Git操作命令
1.初始化一个Git仓库,使用git init
命令
2.添加文件到Git仓库
分两步:
-
使用命令
git add <file>
,注意,可反复多次使用,添加多个文件 -
使用命令
git commint -m <message>
3.掌握工作区的状态命令
如果git status
告诉你有文件被修改过,用git diff
可以查看修改内容
4.增加命令
git add的各种区别:
git add -A // 添加所有改动
git add * // 添加新建文件和修改,但是不包括删除
git add . // 添加新建文件和修改,但是不包括删除
git add -u // 添加修改和删除,但是不包括新建文件
5.撤销命令
在 commit 前撤销 add:
git reset <file> // 撤销提交单独文件
git reset // unstage all due changes
add/commit 前撤销对文件的修改:
git checkout -- README.md // 注意, add添加后(同commit提交后)就无法通过这种方式撤销修改
-
HEAD
指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
-
git log
可以查看提交历史,以便确定要回退到哪个版本 -
git reflog
查看命令历史,以便确定回到很久以前的那个版本
工作区和暂存区
-
工作区指的是电脑里能看到的目录(但
.git
不算工作区,而是Git的版本库) -
暂存区就是图中的
stage
区域 -
图中的
master
是Git自动为我们创建的一个分支,同时Git还自动创建了指向master
的一个指针叫HEAD
工作流程:
-
存在工作区的文件可以分批通过
git add
进入stage
缓存区 -
缓存区的文件经过
git commit
一同进入master
分支
(这里将工作区的文件提交到缓存区时,如果提交单个文件用git add <file_name>
,如果多个文件一同提交用git add .
)
管理修改
Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。
你会问,什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。
如果你的操作如下
第一次修改-->git add
-->第二次修改-->git commit
那么,git commit
只提交了第一次的修改
那么如何提交第二次修改呢
你可以继续git add
把第二次修改的内容整到缓存区,然后再git commit
,把文件整到master
分支上
撤销修改
git restore <file_name>
撤销只在工作区的修改时
git restore --staged <file_name>
撤销已经提交到缓存区的修改
(在老的版本中,git checkout
就是 git restore
. git reset HEAD
就是 git restore --staged
.最新版的git提示都已经更换成了restore)
删除文件
-
第一种情况:在工作区删除了,但想恢复这个文件,并且在这之前已经把文件提到过版本库,那么可以使用命令
git checkout -- <file_name>
可以轻松的把文件恢复到你提交时的那个版本 -
第二种情况:已经把文件提交到版本库,但确实想删除这个文件,那么可以使用命令
git rm <file_name>
删掉,并且git commit
GitHub
关联仓库
要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git
关联后,使用命令git push -u origin master
第一次推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master
推送最新修改;
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!
克隆仓库
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone
命令克隆。
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
分支管理
创建与合并分支
Git鼓励大量使用分支:
-
查看分支:
git branch
-
创建分支:
git branch <name>
-
切换分支:
git checkout <name>
或者git switch <name>
-
创建+切换分支:
git checkout -b <name>
或者git switch -c <name>
(我们注意到切换分支使用git checkout git checkout -- <file>
,同一个命令,有两种作用,确实有点令人迷惑。
实际上,切换分支这个动作,用switch更科学。因此,最新版本的Git提供了新的git switch
命令来切换分支)
-
合并某分支到当前分支:
git merge <name>
-
删除分支:
git branch -d <name>
解决分支冲突
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
用git log --graph
命令可以看到分支合并图。
分支管理策略
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
其实这里的--no--ff
模式其实就是相当于master指针new了一个跟dev指针一样的空间并且放了相同的内容然后指向这个空间。而原来的快速模式,就是简单将master指针指向dev指针指向的内容而已,并没有自己创造空间。
bug分支
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash
一下,然后去修复bug,修复后,再git stash pop
,回到工作现场;
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick <commit>
命令,把bug提交的修改“复制”到当前分支,避免重复劳动。
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-to <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,如果有冲突,要先处理冲突。
Rebase
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
标签管理
创建标签
-
新建一个标签
git tag <tagname>
默认为HEAD,也可以指定一个commit id -
指定标签信息
git tag -a <tagname> -m "blablabla..."
-
查看所有标签
git tag
-
注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
操作标签
-
推送一个本地标签
git push origin <tagname>
-
推送全部未推送过的本地标签
git push origin --tags
-
删除一个本地标签
git tag -d <tagname>
-
删除一个远程标签
git push origin :refs/tags/<tagname>
自定义Git
-
忽略某些文件时,需要编写
.gitignore
-
.gitignore
文件本身要放到版本库里,并且可以对.gitignore做版本管理 -
配置别名比如用
co
表示checkout
就可以使用命令git config --global alias.co checkout
-
配置Git的时候,加上
--global
是针对当前用户起作用的,如果不加,那只针对当前的仓库起作用。
配置文件放哪了?每个仓库的Git配置文件都放在.git/config
文件中:
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
别名就在[alias]
后面,要删除别名,直接把对应的行删掉即可。
而当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig
中:
$ cat .gitconfig
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
配置别名也可以直接修改这个文件,如果改错了,可以删掉文件重新通过命令配置。
到这里就结束啦=====( ̄▽ ̄*)b