完整图文请访问https://github.com/Mrlution/study/tree/master/git
关于repository
我认为repository是一个存放代码代码的地方
使用git
安装
windows安装完毕后要
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
你的电脑里以后可能会有许许多多个项目,每一个项目的代码都放进一个单独的仓库。 config命令的--global参数让你在所有的仓库里面都使用上面的身份。
如果这个身份与github中Public profile配置中的Public email一致,github会在git push之后记录Contributions(profile 那里的绿格子)
创建本地仓库
在本地新建一个目录dir并执行
git init
这个仓库dir就建好了,当前目录下的.git是Git用来跟踪管理版本库的。这个仓库只能跟踪当前目录dir下的文件
将本地文件添加入仓库
在本地新建源文件a.txt后,通过
git add a.txt
将文本文件添加入仓库,或者
git add .
将所有文件添加入仓库,
然后进行必要的说明
git commit -m "wrote a file"
这就是一次提交
连接远程仓库
仓库可以是本地仓库也可以是远程仓库。在连接远程仓库如Github仓库前,你应当在远程建好仓库,并且获得提交到远程仓库的权限。
也就是说,你要
- 新建远程仓库
- 生成ssh key```ssh-keygen -t rsa -C "youremail@example.com"``,将本地的ssh key 添加到github
- 测试是否可以和github通信
ssh git@github.com
。如果有You've successfully authenticated
表示连接成功
当你完成上面的操作后,你在本地有一个仓库dir,在github上有一个仓库study,然后你可以将两个仓库连接起来。
在本地仓库dir下执行
git remote add origin git@github.com:mrlution/study.git
就将本地仓库dir和远程仓库study连接起来了。
接下来
git push -u origin master
将本地master分支推送到远程仓库, -u 参数会将本地master分支和远程master分支关联,下次推送可以不用-u参数,默认推送到远程master分支
版本回退
存档
每次commit就是一次存档,一个版本。每次提交git都会把他们按时间串成一条线。可以从未来回到某一次commit。每次提交都会有一个commit id
查看提交历史
通过
git log
查看最近的提交日志,可以看到commit id
回退
当前版本用HEAD表示,上一个版本用HEAD(或HEAD~1)表示,上上一个版本用HEAD^(或HEAD2)表示,上100个版本用HEAD100表示。
穿越到过去,到达上一次保存,通过
git reset --hard HEAD^
如果要到回到未来,则要找到未来的版本的id
git reflog
上面这条命令会记录你的每一次命令和它的id如如22cc221
然后乘坐时光机
git reset --hard 22cc221
概念解释
工作区
如上面的dir目录就是工作区
版本库
工作区有一个隐藏目录.git,这个就是Git的版本库。Git的版本库里有一个称为stage(或者叫index)的暂存区,还有Git自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
我们把文件往Git版本库里添加的时候,是分两步执行的:
- 用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
- 用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。git commit只负责把暂存区的修改提交了。
可以简单理解为,需要提交的修改通通放到暂存区,再一次性提交暂存区的所有修改到分支。
git status
查看当前状态,例如有哪些修改没有通过git add添加到stage而处于未为commit做好准备的状态,有哪些文件从来没通过git add添加到stage而处于未追踪状态,本地仓库领先远程仓库多少个commits等等
撤销修改
git checkout -- readme.txt
意思就是,把readme.txt文件在工作区的修改全部撤销,根据有没有执行git add分为两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
git reset HEAD -- readme.txt
可以把暂存区的修改撤销掉(unstage),重新放回工作区,然后再执行上面的
git checkout -- readme.txt
把修改从工作区撤销掉
但是如果推送到了远程仓库那么这修改就会被别人看见了
删除文件
工作区删除文件后,使用git rm test.txt
从版本库删除文件
工作区误删文件后,使用git checkout -- test.txt
用版本库里的版本替换工作区的版本或者说成恢复
关于远程仓库是否有人冒充
略
克隆远程仓库
新建一个目录file作为新仓库的工作区,在该目录下
git clone git@github.com:mrlution/study.git
即可将远程的一个仓库克隆到本地。
其实GitHub给出的地址不止一个,还可以用https://github.com/mrlution/study.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。
分支管理
分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN。
如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN!
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上.
你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:
假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:
合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支
新建dev分支
git branch dev
切换到dev分支
git checkout dev
另外git branch
命令可以查看当前分支
dev分支的工作完成,我们就可以切换回master分支:
git checkout master
git merge命令用于合并指定分支到当前分支,把dev分支的工作成果合并到master分支上:
git merge dev
合并完成后,就可以放心地删除dev分支了
git branch -d dev
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。所以,团队合作的分支看起来就像这样:
创建bug分支
假如要修复master分支上的bug,而你在你自己的分支上工作
保存当前工作区,把当前工作现场“储藏”起来,等以后恢复现场后继续工作
git stash
切换到master分支
git checkout master
创建bug分支
git checkout -b issue-101
修复完成后,切换到master分支,并完成合并,最后删除issue-101分支
然后回到原来的工作分支
并且从stash恢复工作现场,同时清空stash
git stash pop
开发新feature也可以像修复bug一样新建分支
多人协作
查看远程库信息,使用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 push origin
推送自己的修改; -
如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
-
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用git push origin
推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to
变基rebase
略
标签
切换到要打标签的分支,为最新的commit打上标签
git tag v1.0
通过commit id为某个历史commit打上标签
git tag v0.9 f52c633
显示所有标签
git tag
Github的使用
点“Fork”就在自己的账号下克隆了一个别人的仓库
如果你希望项目的官方库能接受你的修改,你就可以在GitHub上发起一个pull request
删除原本的远程库关联
git remote rm origin
关连多个远程库
请不要给两个远程库都取名origin
git remote add github git@github.com:michaelliao/learngit.git
git remote add gitee git@gitee.com:liaoxuefeng/learngit.git
推送到github
git push github master
推送到gitee
git push gitee master
git配置
略