一直以来,我们都是使用 svn 作为版本管理工具,对于它的分支管理用得不是很顺,不得不手动管理。
最近发现一本神书 -- 《Pro.Git》,介绍的是 git 版本管理工具,忍不住拜读了前半部分能看懂的。故记录一下。
由于我用的是 windows ,故接下来一切的前提都是在 windows 环境下
msysGit
项目主页下载: http://msysgit.github.com/安装后一般会有一个 Git Bash
和 Git GUI
,我一般用命令行的 Git Bash
,个人感觉命令行能让我更清楚地知道自己的操作,对全局有把控的感觉。
在 git 工作目录下的文件,只有两种状态: 已跟踪
和 未跟踪
。已跟踪 的文件就是已经被纳入版本管理,反之未跟踪就是尚未纳入版本管理的文件。初次使用 git clone
克隆下来的文件都属性已跟踪状态,初次使用 git init
初始化的目录下所有文件都属于未跟踪状态。
已跟踪 后的文件如果有修改则状态更新为 已修改
,git add 已修改的文件将把文件放入 暂存区域
,此时的状态更新为 已暂存
。提交后文件的状态将回归 已跟踪未修改
状态。
如下图,更清晰:
[此处输入图片的描述][http://images.cnblogs.com/cnblogs_com/littledu/619156/o_4.jpg]
初次运行 git 需要先配置一下,就跟不管装什么软件一样,刚装完的时候按我们自己的行为习惯设置一下,如字体,颜色等。git 的配置主要保存我们用户的信息和设置一些默认调用的编辑器等。
git 提供了 git config
命令来完成此操作。
$ git config --global user.name "littledu"
$ git config --global user.email [email protected]
可输入 git config --list
查看所有的配置,更多配置相关点击如下链接了解:
初次运行 Git 前的配置
当配置完后,我们就要开始使用 Git 来工作了。常规的操作有 初始化新仓库、克隆仓库、添加文件纳入版本控制和提交等。
git init
: 初始化新仓库git add
: 添加新文件纳入版本控制并放入暂存区域(选择全部为 git add . 或 git add --all)git commit -m [说明]
: 提交已暂存的更新git commit -a -m [说明]
: 提交全部更新git commit --amend
: 修正最后一次提交git reset HEAD <file>
: 取消已经暂存的文件git checkout -- <file>
: 撤消文件的修改git status
: 检查当前文件状态git diff
: 比较当前文件和暂存区域快照之间的差异git diff --cached
: 暂存起来的文件和上一次提交时快照之间的差异git diff --staged
: 暂存起来的文件和上一次提交时快照之间的差异(Git 1.6.1以上)git log
: 查看提交历史(查看了后按 q 退出)gitk
: 使用图形化工具查阅提交历史git rm
: 从暂存区移除文件,工作目录下的文件也会被删除git rm --cached
: 从暂存区移除文件,保留工作目录下的文件目前基于 git 的远程仓库遍地开花,最有名的如 github
,在上面存放我们的开源代码,能一定程度上提高 逼格
。
git clone [url]
: 克隆现有的仓库git fetch [remote-name]
: 从远程仓库抓取数据到本地,不会自动合并git pull [remote-name]
: 从远程仓库抓取数据到本地,自动合并git push [remote-name] [branch-name]
: 推送数据到远程仓库(加上最后的分支名branch-name可以推送到远程相应分支)git remote
: 查看当前远程仓库的名字git remote -v
: 查看当前远程仓库的详细信息git remote add [shortname] [url]
: 添加远程仓库git remote rename [oldname] [newname]
: 远程仓库重命名git remote rm [remote-name]
: 删除远程仓库(仅移除本地对应的仓库)git 作为版本管理系统,必不可少的要支持 分支
。
为了理解 git 分支的实现方式,我们回顾一下 git 是如何存储数据的。。。。此处省略 1000 字,总之,git 分支是版本控制工具里面最好的。
git branch [branch-name]
: 创建分支(不加参数则为列出所有分支名单)git checkout [branch-name]
: 切换分支git checkout -b [branch-name]
: 创建并切换分支git merge [branch-name]
: 合并分支git mergetool
: 调用可视化合并工具帮忙解决冲突(在遇到冲突时,可以输入此命令,在后续中将自己电脑上装有的 diff 工具如 BC 路径填上,会自动调用其为我们解决冲突)git branch -d [branch-name]
: 删除分支git checkout --track origin/branch-name
: 获取远程分支(默认情况下我们 git clone 都是获取远程 master 分支,如果要获取远程 其他分支,则可以使用这个命令,需 git 1.6.2 以上版本)git checkout -b [new branch-name] origin/[branch-name]
: 同样是获取远程分支,但可以改分支名git push origin :[branch-name]
: 删除远程分支(不能删除 master 分支)时不时的,我们想回到较早前的提交内容(commit),我们可以使用 git reset --hard [commit id]
来回退。commit id
可以通过 git log
来查看,如下图那一长串的 SHA 字符:
但这样回退,是不会有历史记录的,也就是回退了后再执行 git log
将看到在此记录前的记录全没了,如有如下记录:
$ git log --pretty=oneline
ab1afef80fac8e34258ff41fc1b867c702daa24b modified repo a bit
484a59275031909e19aadb7c92262719cfcdf19a added repo.rb
1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
cac0cab538b970a37ea1e769cbbde608743bc96d second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
我将回退到中间的 third commit
$ git reset --hard 1a410efbd13591db07496601ebc7a059dd55cfe9
HEAD is now at 1a410ef third commit
$ git log --pretty=oneline
1a410efbd13591db07496601ebc7a059dd55cfe9 third commit
cac0cab538b970a37ea1e769cbbde608743bc96d second commit
fdf4fc3344e67ab068f836878b6c4951e3b15f3d first commit
会是如上的结果,丢失了两次被跨越的 commit。
所以,不要轻易的跨版本回退(如果能不回退那世界将很美好),但做了想找回也有办法,git 提供了一个 git reflog
命令,可以看到历史上所有的 commit ,也就是可以找回丢失的 commit id
了。
git reset --hard 1a410e....
不需要输入那么长的 id,只需要前几个即可。另外,强烈推荐详细阅读 《Pro.Git》第三章开头介绍的 git 数据存储原理,将对你理解 git 的分支和版本回退有非常大的帮助。
在开发的过程中,总会遇到有一些文件我们不想纳入版本管理,如相关说明文档或日志等。
可以创建一个 .gitignore
文件,列出要忽略的文件或模式,如下例子:
# 此为注释– 将被Git 忽略
*.a # 忽略所有.a 结尾的文件
!lib.a # 但lib.a 除外
/TODO # 仅仅忽略项目根目录下的TODO 文件,不包括subdir/TODO
build/ # 忽略build/ 目录下的所有文件
doc/*.txt # 会忽略doc/notes.txt 但不包括doc/server/arch.txt
注:如何在 windows 下创建一个没有名字的文件请参考:Windows下创建没有名字的文件(.htaccess)最简单的方法
git fetch [remote-name]
git pull [remote-name]
fetch
和pull
都是从远程仓库抓取数据到本地,他们的区别就是 fetch 不会自动合并,而 pull 会自动与本地数据进行合并。
当你使用了 git fetch 后,想查看一下它在哪里时,可以使用:
git branch --all
当你使用了 git fetch 后,想合并它时,可以使用:
git log -p master..origin/master
git merge origin/master
事实上,我个人倾向于直接使用 git pull ,直接了当。
git
常用的命令基本就这些了,这里忽略了 git tag
和 git rebase
命令。1 是因为比较少用,或许是我个人比较少用;2 是因为有另一种方式可以实现相同功能,如 git rebase
可以婉转的用 git merge
代替。
最后,感谢 toobug 大大忍受住了我时不时的骚扰,为我解惑各种 git 疑难杂症。有空给个面子让我请你去喝星巴克最贵的咖啡吧。