初始设置
git config --global user.name "lanbin"
git config --global user.email "[email protected]"
创建仓库
git init
创建完毕目录会多了个.git的隐藏文件夹
版本回退
- HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
- 穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
- 要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
本地仓库
用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
用git status查看状态
用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别
用git checkout -- readme.txt可以丢弃工作区的修改
用git reset HEAD
可以把暂存区的修改撤销掉(unstage),重新放回工作区 用git rm test.txt删掉文件,并且git commit
在文件系统上误操作删除了文件,可以用git checkout -- test.txt还原
GIT把内容按元数据方式存储,而SVN是按文件方式存储,git管理的是修改而不是文件;
SVN在Commit前,我们都建议是先Update一下,跟本地的代码编译没问题,并确保开发的功能正常后再提交,这样其实挺麻烦的,有好几次同事没有先Updata,就Commit了,发生了一些错误,耽误了大家时间,Git可能这种情况会少些。
远程仓库
先有本地库,后有远程库的时候,如何关联远程库
首先登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库
添加到远程仓库
git remote add origin [email protected]:lanbin/learngit.git
远程库的名字就是origin
- 推送到远程仓库
git push -u origin master
先创建远程库,然后,从远程库克隆
- 从远程仓库克隆
$ git clone [email protected]:lanbin/learngit.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
分支管理
HEAD指向的就是当前分支
- git checkout命令加上-b参数表示创建并切换
$ git checkout -b dev
Switched to a new branch 'dev'
- 用git branch命令查看当前分支
$ git branch
* dev
maste
- 切换回master分支
$ git checkout master
Switched to branch 'master'
- 把dev分支的工作成果合并到master分支上
$ git merge dev
Updating d46f35e..b17d20e
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion(+)
- 合并完成后,就可以放心地删除dev分支了
$ git branch -d dev
Deleted branch dev (was b17d20e
Git鼓励大量使用分支:
- 查看分支:git branch
- 创建分支:git branch
- 切换分支:git checkout
- 创建+切换分支:git checkout -b
- 合并某分支到当前分支:git merge
- 删除分支:git branch -d
冲突管理
如果存在冲突,将合并失败并有提示
$ 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 status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add ..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
可以直接查看readme.txt的内容
Git is a distributed version control system.
Git is free software distributed under the GPL.
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 log也可以看到分支的合并情况
$ git log --graph --pretty=oneline --abbrev-commit
* cf810e4 (HEAD -> master) conflict fixed
|\
| * 14096d0 (feature1) AND simple
* | 5dc6824 & simple
|/
* b17d20e branch test
* d46f35e (origin/master) remove test.txt
* b84166e add test.txt
* 519219b git tracks changes
* e43a48b understand how stage works
* 1094adb append GPL
* e475afc add distributed
* eaadf4e wrote a readme file
- 用git log --graph命令可以看到分支合并图。
- 当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成
- 解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。
分支管理策略
- master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
- dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
- 开发者都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
BUG分支
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash,然后去修复bug,修复后,再git stash pop,回到工作现场。
- 用git stash命令把工作现场“储藏”起来
$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge
- 用git stash list命令看看储存清单
$ git stash list
stash@{0}: WIP on dev: f52c633 add merge
用git stash apply从储存恢复到工作现场,恢复后stash内容并不删除
用git stash drop命令来删除储存
git stash pop = git stash apply + git stash drop
feature分支
- 开发一个新实验功能,最好新建一个分支;
- 如果要丢弃一个没有被合并过的分支,可以通过git branch -D
强行删除;
推送分支
查看远程库信息,使用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,如果有冲突,要先处理冲突。
哪些分支需要推送,哪些不需要呢?
- master分支是主分支,因此要时刻与远程同步;
- dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
- bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
- feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
合并分支
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:
$ git rebase --continue
这样git会继续应用(apply)余下的补丁。
在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态
$ git rebase --abort
标签管理
- 命令git tag
用于新建一个标签,默认为HEAD,也可以指定一个commit id; - 命令git tag -a
-m "blablabla..." 可以指定标签信息;- 命令git tag可以查看所有标签。
- 命令git show
查看标签信息 - 命令git push origin
可以推送一个本地标签; - 命令git push origin --tags可以推送全部未推送过的本地标签;
- 命令git tag -d
可以删除一个本地标签; - 命令git push origin :refs/tags/
可以删除一个远程标签。
使用github
- 在GitHub上,可以任意Fork开源仓库
eg. https://github.com/twbs/bootstrap - 自己拥有Fork后的仓库的读写权限;
点“Fork”就在自己的账号下克隆了一个bootstrap仓库,然后从自己的账号下clone
git clone [email protected]:lanbin/bootstrap.git
- 可以推送pull request给官方仓库来贡献代码。
对方是否接受你的pull request就不一定了
使用码云gitee
廖雪峰Git教程-使用码云
自定义Git
忽略特殊文件
- 忽略某些文件时,需要编写.gitignore;
- .gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理
参考文献
- 廖雪峰Git教程
- Git Community Book 中文版