[TOC]
说明
本篇文章是本人回顾git知识点时从《progit》一书中摘抄出来的笔记,毕竟好记性不如烂笔头嘛,不然我也不会回顾了……
另请大神绕路,不喜勿喷……
1 基础知识
初始提交
$ git init repo-1
Initialized empty Git repository in H:/tmp/git-test/repo-1/.git/
$ cd repo-1/
# 建立三个测试文件
$ touch readme.md config.xml db.properties
# 加入暂存区 待下次提交
$ git add readme.md config.xml db.properties
# 提交
$ git commit -m 'init project'
此时的git仓库中的对象可能大致如下图所示:
说明:
- blob对象:保存着文件快照
- tree对象:记录着目录结构和blob对象索引
- commit对象:包含着指向前述树对象的指针和所有提交信息
做些修改再提交
# 修改readme.md
$ echo "haha" >> readme.md
$ git add .
$ git commit -m "second commit"
# 修改db.properties
$ echo "db.user=root" >> db.properties
$ git add .
$ git commit -m "db.properties modified"
# 看看此时的提交历史
$ git log --oneline --decorate --all
7240135 (HEAD -> master) db.properties modified
828bc57 second commit
e314b67 init project
此时的仓库中快照可能是下面这个样子:
就像前面说的,git不存储文件差异,每次提交都是记录一次文件的快照,担任文件内容不变的时候不会重复存储快照了。
每个commit一般都有其父commit对象(除了第一个commit对象)。
git的分支本质也就是指向某个特定commit对象的指针。
这样的话,在分支切换、分支建立的时候,都是非常迅速的。
当你首次提交之后,git会建立一个名为master的默认分支。即使你不显示地主动创建分支,你也是在master分支上工作的。每次提交后,都是指向最后一个commit对象。也就是说,在commit的时候这个指针是自动移动的。
在你创建新分支的时候,其实是创建了一个新的指针。
2 分支基本操作
2.1 新建分支
# 建立名为b1的分支
$ git branch b1
此时的分支信息如下所示:
- 此时的master和b1分支都指向最新的一个commit对象
- 上图中的HEAD指的是一个记录当前所处本地分支的指针。也就是说HEAD是当前分支的别名
- 在你使用
git branch b1
建立分支后,并没有自动切换到新分支b1上去
# 此时的b1和master都是指向特征码为7240135的commit对象
# HEAD -> master表明,当前所处分支任然是master分支
$ git log --oneline --decorate
7240135 (HEAD -> master, b1) db.properties modified
828bc57 second commit
e314b67 init project
2.2 切换分支
$ git checkout b1
Switched to branch 'b1'
# HEAD -> b1 表明,当前所处分支是b1
$ git log --oneline --decorate
7240135 (HEAD -> b1, master) db.properties modified
828bc57 second commit
e314b67 init project
HEAD -> b1 表明,当前所处分支是b1。那么此时的分支图示应该像下面这样:
2.3 新分支上做修改
# 在分支b1上修改文件readme.md
$ echo "new line @ brach b1" >> readme.md
$ git add readme.md
$ git commit -m "modified on b1 - 1"
查看此时的提交历史
$ git log --oneline --decorate
cf385f4 (HEAD -> b1) modified on b1 - 1
7240135 (master) db.properties modified
828bc57 second commit
e314b67 init project
可以得出:
- 最新的一次commit对象是在分支b1上做的
- 当下处于b1分支
那么此时的分支示例图大概如下:
2.4 分支合并
回到master分支
$ git checkout master
Switched to branch 'master'
$ git log --decorate --oneline
7240135 (HEAD -> master) db.properties modified
828bc57 second commit
e314b67 init project
在master分支上修改db.properties
$ cat db.properties
db.user=root
# 在master分支上修改db.properties
$ echo "db.password=123" >> db.properties
$ git add db.properties
$ git commit -m "db.properties modified on master"
此时的分支示例图
$ git log --decorate --oneline --graph
* 957a3d0 (HEAD -> master) db.properties modified on master
* 7240135 db.properties modified
* 828bc57 second commit
* e314b67 init project
- 此时分支已经有了分叉
- 可以在需要的时候合并
合并b1分支到master
$ git merge b1
Merge made by the 'recursive' strategy.
readme.md | 1 +
1 file changed, 1 insertion(+)
查看分支历史
$ git log --decorate --oneline --graph
* 3115451 (HEAD -> master) Merge branch 'b1'
|\
| * cf385f4 (b1) modified on b1 - 1
* | 957a3d0 db.properties modified on master
|/
* 7240135 db.properties modified
* 828bc57 second commit
* e314b67 init project
3 分支管理
列出所有分支
$ git branch
b1
* master
删除分支
git branch -d <branch-name>
master分支前面的星号表示当前HEAD指向master,也就是说当前处于master分支。
查看每一个分支的最后一次提交
$ git branch -v
b1 cf385f4 modified on b1 - 1
* master 3115451 Merge branch 'b1'
查看已经合并到/尚未合并到当前分支的分支
# b1分支已经合并到当前分支
$ git branch --merged
b1
* master
# 尚未合并到当前分支的分支
$ git branch --no-merged
此处使用 git branch --merged
列出的这个列表中分支名字前没有星号的分支通常可以使用 git branch -d
删除掉。因为在这些分支上所作的修改已经被合并到其他分支了。
4 远程仓库与远程分支
4.1 远程仓库
远程仓库是指托管在因特网或其他网络中的项目的版本库。可以有若干个远程仓库。
$ git clone https://github.com/java-template/jt-808-protocol.git
$ cd jt-808-protocol/
# 列出指定的每一个远程服务器的简写
(master) $ git remote
origin
(master) $ git ls-remote
From https://github.com/java-template/jt-808-protocol.git
7c86e1cde856183e794b31ac72f2b02377b6f4b8 HEAD
7c86e1cde856183e794b31ac72f2b02377b6f4b8 refs/heads/master
# 选项 -v,显示简写与其对应的 URL
(master) $ git remote -v
origin https://github.com/java-template/jt-808-protocol.git (fetch)
origin https://github.com/java-template/jt-808-protocol.git (push)
4.2 远程仓库管理
新增远程仓库
git remote add <name> <url>
# 添加简写名为another的远程仓库
(master) $ git remote add another https://github.com/java-template/jt-808-protocol.git
# 列出所有的远程仓库
(master) $ git remote -v
another https://github.com/java-template/jt-808-protocol.git (fetch)
another https://github.com/java-template/jt-808-protocol.git (push)
origin https://github.com/java-template/jt-808-protocol.git (fetch)
origin https://github.com/java-template/jt-808-protocol.git (push)
# 此时可以使用another来代替整个URL来使用
(master) $ git pull another
From https://github.com/java-template/jt-808-protocol
* [new branch] master -> another/master
You asked to pull from the remote 'another', but did not specify
a branch. Because this is not the default configured remote
for your current branch, you must specify a branch on the command line.
注意
- 如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以
origin
为简写
重命名远程仓库
# 将远程服务器another重命名为other
(master) $ git remote rename another other
(master) $ git remote -v
origin https://github.com/java-template/jt-808-protocol.git (fetch)
origin https://github.com/java-template/jt-808-protocol.git (push)
other https://github.com/java-template/jt-808-protocol.git (fetch)
other https://github.com/java-template/jt-808-protocol.git (push)
删除远程仓库
# 删除远程服务器other
(master) $ git remote rm other
(master) $ git remote -v
origin https://github.com/java-template/jt-808-protocol.git (fetch)
origin https://github.com/java-template/jt-808-protocol.git (push)
4.3 从远程仓库获取数据
git fetch [remote-name]
- 此命令会访问远程仓库,从中拉取所有你还没有的数据
- 执行完成后,你将会拥有那个远程仓库中所有分支的引用
- 但是此命令并不会自动
merge
,也就是说需要你手动合并
git pull
- 该命令可以认为是
git fetch
和git merge
的组合 - 当然,自动合并出错还得你自己解决冲突了
4.4 推送数据到远程分支
远程分支以 (remote)/(branch)
形式命名,或称之为唯一标识它。
比如origin/master
表示远程服务器orgin上的master分支,origin/iss256
表示origin服务器上的一个名为iss256的分支。
git push [remote-name] [branchname]
将 master 分支推送到 origin 服务器
$ git push origin master
4.5 一点说明
当clone一个远程仓库时,会自动建立一个master分支来跟踪origin/master分支
- origin是默认的远程服务器的名称
- master是默认的分支名
- 当然,origin和master除了是默认的名称外,没有其他任何特别之处
至于跟踪分支的细节,请看下文
5 跟踪分支
跟踪分支是与远程分支有直接关系的本地分支。
也就是说:在一个跟踪分支
上执行 git pull
,Git 能自动地识别去哪个服务器上抓取、也知道将fetch到的数据合并到哪个分支。
5.1 创建跟踪分支
- 当clone一个远程仓库时,会自动建立一个
master
分支来跟踪origin/master
分支 - 使用
git checkout -b [branch] [remotename]/[branch]
创建跟踪分支 - 或者可以在checkout的时候使用
--track
选项
# 创建一个名为another-track-branch的分支作为origin/master的跟踪分支
(master) $ git checkout -b another-track-branch origin/master Branch another-track-branch set up to track remote branch master from origin.
Switched to a new branch 'another-track-branch'
(another-track-branch) $
5.2 修改跟踪分支
可以使用 -u
或 --set-upstream-to
选项运行 git branch
来显式地设置跟踪的远程分支
# 设置当前分支跟踪origin服务器的master分支
(another-track-branch) $ git branch --set-upstream-to origin/master
5.3 查看跟踪分支
(another-track-branch) $ git branch -vv
* another-track-branch 7c86e1c [origin/master] 调试工具
master 7c86e1c [origin/master] 调试工具
test1 7c86e1c 调试工具
(another-track-branch) $ git branch -vv
可以看出,此处:
- another-track-branch分支和master分支都在跟踪origin/master分支
- another-track-branch前面的星号表示目前处于another-track-branch分支
- test1分支没有跟踪任何分支
参考资料
- 《progit》