HEAD
简介
git 是通过HEAD来确定你当前在哪个分支上工作。HEAD是指向分支(例如master),分支指向提交(可以直接理解为HEAD指向的是当前分支当前提交版本)。
我们的主线往往是一根直线,多一个分支相当于多一个分叉,无数分支纵横交错就像一颗树状的结构,所以我们称之为目录树。commit rebase reset merge这些都是改变目录树的操作。
符号
^x: 尖头符号,形似箭头,表示要朝那个方向,始终是走一步,x 表示第几个岔路口,代表方向盘
~y: 波浪符号,表示要在该方向上走 y 步,始终沿着该方向,代表油门
示例
自己: HEAD, HEAD^0 或 HEAD~0
父亲: HEAD^, HEAD~
母亲: HEAD^2
爷爷: HEAD^~, HEAD~2, HEAD^^
奶奶: HEAD^^2, HEAD~^2
姥爷: HEAD^2~, HEAD^2^
姥姥: HEAD^2^2
origin
origin 是远程仓库的名字,可以在 .git/config 之中进行修改。代码库(repository)可以存放在本地,也可以存放到远程。默认origin指向的是远程仓库。
若通过git clone https://github.com/user1/repository命令克隆下来代码,则git remote -v的结果为:
origin https://github.com/user1/repository.git (fetch)
origin https://github.com/user1/repository.git (push)
一般会使用git remote add origin xxx(远程仓库地址),也可以用其他名字,例如:git remote add upstream https://github.com/user2/repository.git,用git remote -v查看:
origin https://github.com/user1/repository.git (fetch)
origin https://github.com/user1/repository.git (push)
upstream https://github.com/user2/repository.git (push)
upstream https://github.com/user2/repository.git (push)
master、origin master 与 origin/master
其他网址
master、origin master 与 origin/master - 简书
简介
- master
- 它代表本地的某个分支名。
- origin master
- 代表着两个概念:前面的origin代表远程名,后面的master代表远程分支名。
- origin/master
- 只代表一个概念,即远程分支名,是从远程拉取代码后在本地建立的一份拷贝(因此也有人把它叫作本地分支)。
举几个例子可能会更加清晰地说明问题
- git fetch origin master
- 它的意思是从名为 origin 的远程上拉取名为 master的分支到本地分支origin/master` 中
- 既然是拉取代码,当然需要同时指定远程名与分支名,所以分开写。
- git merge origin/master
- 它的意思是合并名为 origin/master 的分支到当前所在分支。
- 既然是分支的合并,当然就与远程名没有直接的关系,所以没有出现远程名,需要指定的是被合并的分支。
- git push origin master
- 它的意思是推送本地的 master 分支到远程 origin
- 涉及到远程以及分支,当然也得分开写了。
- git fetch origin master stable oldstable;
- 一次性拉取多个分支的代码
- git merge origin/master hotfix-2275 hotfix-2276 hotfix-2290;
- 一次性合并多个分支的代码
fetch和pull区别
其他网址
准备工作
每一个本地库下都有一个.git的隐藏文件夹,文件夹中的文件保存着跟这个本地库相关的信息
首先来看下其中的config文件
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "origin"]
url = git@github.com:seanzou88/fetch.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
从这个文件中我们可以了解到:
1,本地库的当前分支为master,其关联的远程库名称为origin(不同的名称可以指向同一个远程库,参见git remote命令)
2,远程库origin所在的位置为(URL):git@github.com:seanzou88/fetch.git
然后可以查看.git文件夹下的HEAD文件:ref: refs/heads/master
其指向.git\refs\heads\master文件:ce71505b3626a3648b2c32ea2081d65049cad300
这个文件中保存的是本地库中最新的commit id
.git\refs文件夹很有意思,里面分为3个文件夹
- heads文件夹:前面说过了
- remotes文件夹:中的每一个文件夹代表一个远程库名称(git remote),其中的每个文件关联远程库的一个分支,其中保存该分支的最新commit id
- .git\logs文件夹:保存的是.git\refs文件夹下相应文件的变更记录
准备工作到此结束,下面可以具体看看git fetch和git pull之间的区别了。
git fetch和git pull的区别
git fetch origin
本地的latest commit id为:ce71505b3626a3648b2c32ea2081d65049cad300
githup上的latest commit id为:ab8cd391f978fe5384a78c92001ef8ae861046f0
before:
.git\refs\heads\master:ce71505b3626a3648b2c32ea2081d65049cad300
.git\refs\remotes\origin\master:ce71505b3626a3648b2c32ea2081d65049cad300
.git\logs\refs\heads\master:
0000000000000000000000000000000000000000
ce71505b3626a3648b2c32ea2081d65049cad300
......
commit (initial): first commit
.git\logs\refs\remotes\origin\master:
0000000000000000000000000000000000000000
ce71505b3626a3648b2c32ea2081d65049cad300
......
update by push
after:
.git\refs\heads\master(不变)
.git\refs\remotes\origin\master:ab8cd391f978fe5384a78c92001ef8ae861046f0
.git\logs\refs\heads\master(不变)
.git\logs\refs\remotes\origin\master
0000000000000000000000000000000000000000
ce71505b3626a3648b2c32ea2081d65049cad300
......
update by push
ce71505b3626a3648b2c32ea2081d65049cad300
ab8cd391f978fe5384a78c92001ef8ae861046f0
......
fetch origin: fast-forward
本地库并没有变化,也就是说,git fetch只会将本地库所关联的远程库的commit id更新至最新
HEAD没有变化很容易理解,因为本地库并没有变化
git pull origin master:master
本地的latest commit id为:3643a1a65fc88ae0e9f28f12168629758d027415
githup上的latest commit id为:64df093f73294d82a3adce9694871b9fac2aecfb
before:
.git\refs\heads\master:3643a1a65fc88ae0e9f28f12168629758d027415
.git\refs\remotes\origin\master:3643a1a65fc88ae0e9f28f12168629758d027415
.git\logs\refs\heads\master
0000000000000000000000000000000000000000
3643a1a65fc88ae0e9f28f12168629758d027415
......
commit (initial): first commit
.git\logs\refs\remotes\origin\master
0000000000000000000000000000000000000000
3643a1a65fc88ae0e9f28f12168629758d027415
......
update by push
after:
.git\refs\heads\master:64df093f73294d82a3adce9694871b9fac2aecfb
.git\refs\remotes\origin\master(不变)
.git\logs\refs\heads\master:
0000000000000000000000000000000000000000
3643a1a65fc88ae0e9f28f12168629758d027415
......
commit (initial): first commit
3643a1a65fc88ae0e9f28f12168629758d027415
64df093f73294d82a3adce9694871b9fac2aecfb
......
pull origin master:master: fast-forward
.git\logs\refs\remotes\origin\master(不变)
- 本地库更新至最新,git pull会将本地库更新至远程库的最新状态。
- 由于本地库进行了更新,HEAD也会相应的指向最新的commit id。
- 所以虽然从结果上来看,git pull = git fetch + git merge,但是从文件中保存的commit id来看,实现上不是这样实现的
为了更好的理解,画了个图:
git reset --hard恢复
实习生的代码被弄丢了!救命的时候绝对用的上——每天三分钟玩转Git (8)