1.基本概念
工作区:就是在电脑里能看到的存放代码文件的目录。
版本库:工作区有一个名称为.git隐藏目录,这个就是Git的版本库。
暂存区:Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
使用命令git help <command>查看command的用法。
2.配置工具
配置本地所有仓库的用户信息
$ git config --global user.name "[name]"
设置用于提交事务用户名,--global参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有用。
$ git config --global user.email "[email address]"
设置用于提交事务的邮件地址
$ git config --global color.ui auto
启用命令行输出的有用彩色化
$ git config --global –list
查看设置的用户名和Email
3.创建仓库
启动一个新的存储库或从现有URL获取一个仓库。
$ git init [project-name]
初始化git,然后git就可以管理这个目录中的所有内容了
$ git clone [url]
下载项目及其整个版本历史
4.添加与提交
$ git status
列出所有要提交的新文件或修改的文件,会显示如下内容:
changes to be commited:表示将要提交但是尚未提交的修改(已经add但是尚未commit),也就是在stage区域已经有了,但是还没有commit的内容
changed but not updated:表示已经修改但是还没有添加到暂存区的内容(尚未add,当然尚未commit)
$ git add [file]
告诉git我要添加一个文件,但是git并没有把你所添加的文件放入版本库中,而是对内容进行hash后生成了一个编号,相当于添加内容的身份证号,将该身份证号添加到版本库index,即告诉git我有一个文件编号XXX的内容将要提交,但是并没有真正提交到版本库(如下图),要想将文件真正放入版本库需要commit
$ git commit -m "[descriptive message]"
提交,-m参数是提交留言,说明为什么要提交的更新做了什么事情。注意:只有add后提交才有效。“改文件->add文件->再改->提交”,则第二次修改无效,不会被提交,只会成功提交第一次的修改。
$ git commic -C HEAD -a –amend
增补提交,用head上次提交的留言(-C表示comments),将这次的提交追加到上一次提交上,不会创建新的提交代号
$ git diff
比较working directory和stage(index)的差别
$ git diff --staged
查看暂存的和文件最后一个版本的差异
$ git diff --cached
查看stage(index)和History(当前分支版本库)之间的差异
$ git reset [file]
将文件从暂存区取出,但保留其内容
$ git diff HEAD
直接比较working directory 和history的区别
$ git blame hello.cpp
问责文件内容,查看所用向hello.cpp提交内容的人,方便问责到人,谁,什么时候,提交代号,提交内容,留言等都会显示
对下图的说明:
working directory是当前的工作目录,
stage是暂存区也称索引区存放工作目录中那些你打算提交到版本库的变更。
History就是版本库,需要注意的是这是本地的版本库,存在于本地的电脑中,相当于你电脑上一个你的私人钱财管理员。
git add只是将文件的索引提交的版本库,而真正的内容并没有进入版本库。
5.组变化
git可以使用多条分支,这样就可以在不影响当前进度的情况下,用创建新的分支的方法来进行接下里的开发,分支使用的原则,一般来说:
1. 试验性修改(常用):测试新的算法或者为某个特别的模式重构部分代码
2. 增加新功能(常用):为每个新功能的开发创建新的分支,完成该功能开发后,在将其合并到主分支上
3. Bug修改:修复代码中的bug,可以创建新分支来对该bug进行修改,然后将修改合并到主分支上
$ git branch
查看分支,查看前版本库(本地)的所有分支
$ git branch [branch-name]
创建分支,创建一个名为branch-name新分支
git checkout -b [branch-name]
创建并切换,相当于以下两条命令:git branch [branch-name]和git checkout [branch-name]
$ git checkout [branch-name]
切换分支,切换到名为branch-name的分支,并更新工作目录。切换到“要合并到”的分支,常见的就是test分支合并到master分支,所以先切换到master分支
$ git checkout -b branch-name origin/branch-name
在本地创建和远程分支对应的分支,建议,本地和远程分支的名称最好一致;
$ git branch --set-upstream branch-name origin/branch-name
建立本地分支和远程分支的关联
$ git merge [branch]
合并分支,合并branch分支到master分支
$ git branch -d [branch-name]
删除分支,删除特定分支
$ git branch -m test test2
分支重命名,将test分支重命名为test2,这个命令不常用
6.重构文件
重新定位和删除版本化的文件
$ git rm [file]
从工作目录中删除file文件,并将暂存删除记录
$ git rm --cached [file]
从版本控制中删除该文件,但在本地保留该文件
$ git mv [file-original] [file-renamed]
更改文件名并准备提交
7.抑制跟踪
排除临时文件和路径,如下
*.log
build/
temp-*
名为.gitignore的文本文件禁止对匹配指定paterns的文件和路径进行意外版本控制。
$ git ls-files --other --ignored --exclude-standard
列出此项目中所有被忽略的文件
8.工作现场处理
$ git stash
保存工作现场,临时存储所有修改后的跟踪文件
$ git stash apply
恢复工作现场,但是恢复后,stash内容并不删除,有多个工作现场时可以git stash apply stash@{0}恢复特定的现场
$ git stash pop
恢复的同时也把stash内容删除了
$ git stash list
查看工作现场,列出所有临时存储的变化集
$ git stash drop
删除stash的内容
9.查看历史记录
浏览和检查项目文件的演变
$ git log
查询所有的commit历史
查询指定范围的commit历史:
$ git log --since = "5 hours"
查看最近5小时的commit历史记录
$ git log --before = "5 hours" -2
查看5小时之前最后2次的提交commit记录
$ git log 18f822e..0bb3dfb
查看从18f822e(不包括18f822e)到0bb3dfb之间的提交记录
$ git log 18f822e..HEAD
HEAD表示当前所在分支的最新版本,即HEAD指向当前所在分支的最后一次commit
git log HEAD^^^
^表示父节点,HEAD^就表示HEAD的父节点,以此类推
git log HEAD~3
~N表示回溯N个节点,所以与上一个表述等价
$ git log --follow [file]
列出文件的版本历史记录,包括重命名
git log --graph --pretty=oneline --abbrev-commit
查看分支合并情况,用git log --graph命令可以看到分支合并图。
$ git diff [first-branch]...[second-branch]
列出两个分支的内容差异
$ git show [commit]
输出指定提交的元数据和内容更改
10.重新提交
$ git reset [commit]
在提交之后撤消所有提交,在本地保存更改
$ git reset --hard 某版本号[前几位]
丢弃所有历史记录并更改返回到指定的版本号,不一定要全部的版本号,就像这个命令的例子,只要前面的约7、8位就可以。
$ git checkout -- 文件名
把没暂存(即没add)的干掉,或者说,丢弃工作区,回到到暂存状态
$ git reset HEAD 文件名
把暂存的状态取消,工作区内容不变,但状态变为“未暂存”
11.版本库同步
$ git fetch origin
这个命令查找“origin”是哪一个服务器,从中抓取本地没有的数据,并且更新本地数据库,移动origin/master指针指向新的、更新后的位置
$ git pull
拖入(pull)远程版本库,与本地分支合并,相当于 git fetch + git merge
$ git remote -v
查看远程库信息
$ git remote add origin https://github.com/register/reponame.git
为远程版本库reponame取别名origin
$ git push [origin] [master]
将本地master分支推入远端origin的master,如果推送失败,先用git pull抓取远程的新提交;
git push origin serverfix:awesomebranch
将本地的 serverfix分支推送到远程origin仓库上的awesomebranch分支
git push origin --delete serverfix
删除远程的serverfix分支
$ git pull
拉取历史并合并变化
12.其他
还有一些不是很常用的操作简单的列在下面,如果用到这些命令,可以参看git doc或者本文参考文献中所列的内容,不一一赘述。
$ git revert
翻转提交
$ git reset
复位
$ git rebase master
分支变基,在当前分支(非master)下执行该命令,则相当于把当前分支和mater分支合并,和merge操作类似,但提交历史不同,rebase操作的log更干净。
$ git tag
查看所有标签
$ git push origin tagname
推送一个本地标签
$ git push origin --tags
可以推送全部未推送过的本地标签
$ git tag -d tagname
可以删除一个本地标签
$ git push origin :refs/tags/tagname
可以删除一个远程标签
$ git submodule
git子模块
$ git archive
导出版本库
$ git bisect
二分查找
13.SSH KEYGEN
$ ssh-keygen -t rsa -C "youremail@example.com"
创建ssh keygen
git remote add origin git@server-name:path/repo-name.git
要关联一个远程库,关联后,使用命令git push -u origin master第一次推送master分支的所有内容;此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改。
14.分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
$ git merge --no-ff -m "merge with no-ff" dev
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。
开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D name强行删除。