学习资料:
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
http://codingnow.cn/version/212.html
http://blog.jobbole.com/34503/
http://www.cnblogs.com/lwzz/archive/2013/02/23/2921426.html
Git即集中式版本控制系统。mac上的安装:直接从AppStore安装Xcode,Xcode集成了Git,选择菜单“Xcode”->“Preferences”,在弹出窗口中找到“Downloads”,选择“Command Line Tools”,点“Install”就可以完成安装了。
1.版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
- 初始化一个Git仓库,使用
git init
命令。 - 更新一个Git仓库,即添加文件到Git仓库,分两步: (add放到暂存区(stage),commit放到工作区)
-
- 第一步,使用命令
git add <file>
,注意,可反复多次使用,添加多个文件; - 第二步,使用命令
git commit
,完成。-m “xxx”
本次提交的说明。Git跟踪并管理的是修改,而非文件,表现在git commit
只负责把暂存区的修改提交了。
- 第一步,使用命令
- 查看仓库状态,即距离上个更新版本有哪些更改。
- git status哪些文件更改了(有没有放到暂存区也显示)。一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的.
- git diff <file>更改了什么。
- 查看仓库更新的历史纪录,
git log
命令显示从最近到最远的提交日志,可以看到3次提交。 - 到指定版本:
- 用
HEAD
表示当前版本,HEAD^是上一个版本,
HEAD^^是上上一个版本
,HEAD~100往上100个版本。
- 用
git reset --hard HEAD^ 回退到上一个版本“add distributed”
-
- 通过版本号(hash id)转到某一版本。版本号没必要写全,前几位就可以了,Git会自动去找。
git reset --hard 3628164
-
- Git提供了一个命令
git reflog
用来记录你的每一次命令。可以通过此找到版本号回到“未来版本”。
- Git提供了一个命令
Ps:Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD
指针,当你回退版本的时候,Git仅仅是把HEAD修改指针,同时更新工作区。
- git checkout -- <file> 让这个文件回到最近一次
git commit
或git add
时的状态。 没有--
,就变成了“创建一个新分支”的命令 - 与add对应,rm是删除某文件,也要commit生效。撤销删除可以用checkout --
2.远程仓库
只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。
找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。
由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:
- 创建SSH Key。
- 登陆GitHub添加SSH Key。
1)使用remote add把本地仓库的内容关联到远程仓库(至少先创建个空到远程仓库)。
$ git remote add origin [email protected]:<git账户名>/<本地仓库名>.git
添加后,远程库的名字就是origin
,这是Git默认的叫法。
使用命令push第一次推送master分支的所有内容,以后再push不需要加-u。
git push -u origin master
2)先有远程库,然后,从远程库克隆。
git clone [email protected]:<git账户名>/<远程仓库名>.git
地址还可以是https://github.com/michaelliao/gitskills.git
这样的地址,支持ssh和http两种协议。
3.分支
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
1)
- 每个节点是一次commit,用时间线链接起来,分支其实是指向节点的指针,创建、切换、合并、删除分支等操作其实都是在操作指针。
git checkout -b feature1 //创建一个新分支feature1并切换 git checkout master //切换回maseter
- 当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
git status
可以告诉我们冲突的文件。可以直接查看冲突文本,Git用<<<<<<<
,=======
,>>>>>>>
标记出不同分支的内容。
git merge feature1 git status
git add readme.txt git commit -m "conflict fixed"
git log --graph --pretty=oneline --abbrev-commit //用带参数的git log
可以看到分支的合并情况
git branch -d feature1 //删除分支feature1
合并分支时,加上--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。
git merge --no-ff -m "merge with no-ff" dev
- 分支策略
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
-
- 修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;当手头工作没有完成时,先把工作现场
git stash
一下,然后去修复bug,修复后,再git stash pop
,回到工作现场。 - 开发一个新feature,最好新建一个分支;如果要丢弃一个没有被合并过的分支,可以通过
git branch -D <name>
强行删除。
- 修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;当手头工作没有完成时,先把工作现场
2)与远程仓库关于分支的交互
- 查看远程库信息,使用
git remote -v
; - 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交;
-
master
分支是主分支,因此要时刻与远程同步;dev
分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;- bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
- feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
- 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致; - 建立本地分支和远程分支的关联,使用
git branch --set-upstream branch-name origin/branch-name
; - 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
手册:
- git help <命令> 可以看doc。
- The most commonly used git commands are:
add Add file contents to the index
bisect Find by binary search the change that introduced a bug
branch List, create, or delete branches
checkout Checkout a branch or paths to the working tree
clone Clone a repository into a new directory
commit Record changes to the repository
diff Show changes between commits, commit and working tree, etc
fetch Download objects and refs from another repository
grep Print lines matching a pattern
init Create an empty Git repository or reinitialize an existing one
log Show commit logs
merge Join two or more development histories together
mv Move or rename a file, a directory, or a symlink
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
rebase Forward-port local commits to the updated upstream head
reset Reset current HEAD to the specified state
rm Remove files from the working tree and from the index
show Show various types of objects
status Show the working tree status
tag Create, list, delete or verify a tag object signed with GPG