Jiarui's Blog.

Git Command Notes

2018/05/04 Share

Introduction

Git 的三种状态

Git 有三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。

  • 已提交:表示数据已经安全的保存在本地数据库中。

  • 已修改:表示修改了文件,但还没保存到数据库中。

  • 已暂存:表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

由此引入 Git 项目的三个工作区域的概念:Git 仓库、工作目录以及暂存区域。

areas

Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,拷贝的就是这里的数据。

工作目录是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。

暂存区域是一个文件,保存了下次将提交的文件列表信息,一般在 Git 仓库目录中。 有时候也被称作`‘索引’’,不过一般说法还是叫暂存区域。

基本的 Git 工作流程如下:

1 在工作目录中修改文件。

2 暂存文件,将文件的快照放入暂存区域。

3 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录

记录每次更新到仓库

工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。

编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。 我们逐步将这些修改过的文件放入暂存区,然后提交所有暂存了的修改,如此反复。所以使用 Git 时文件的生命周期如下:

lifecycle.png

Github 的使用

本地SSH Keys的设置

我们需要通过SSH来让本地编辑的内容托管到Github,所以要对先SSH进行设置。

首先检查电脑上现有的SSH Keys,在Terminal输入

1
$ cd ~/.ssh

输入 ls 查看是否有ssh keys。

1
$ ls

如果只显示一个 known_hosts ,说明没有ssh keys,可以跳过这一步,否则需要备份和移除原来的SSH Keys

1
2
3
4
(显示  id_rsa  id_rsa.pub  known_hosts)
$ mkdir key_backup
$ cp id_rsa* key_backup
$ rm id_rsa*

输入以下代码形成新的SSH Key文件,我们只需要默认设置就好,所以当需要输入文件名的时候,回车就好。

1
2
3
4
5
$ ssh-keygen -t rsa -C “your-email”

显示:
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/your_user_directory/.ssh/id_rsa):<回车就好>

上面代码中的 “your-email” 就是你在学习Git时,你自己设置的Git用户名时给出的email地址 ( 我的话,使用的是注册github的email )。

然后系统会要你输入加密串(Passphrase):

1
2
Enter passphrase (empty for no passphrase):<输入加密串>
Enter same passphrase again:<再次输入加密串>

最后看到SSH Key success,就成功设置SSH Key了。

添加SSH Key到GitHub

在本机设置SSH Key之后,需要添加到 GitHub 上,以完成SSH链接的设置。输入下面代码打开SSH文件夹

1
$ open ~/.ssh

用文本编辑工具打开 id_rsa.pub 文件。

登录Github,点击右侧自己的头像,选择 “setting” 。选择右侧的 “SSH and GPG Keys” 项,把 id_rsa.pub 文件中的内容复制到如下位置,然后点击 Add Key 按钮即可。

输入下面的命令,看看设置是否成功,`git@github.com` 的部分不要修改:

1
$ ssh -T git@github.com

如果是下面的反应:

1
2
3
The authenticity of host 'github.com (207.97.227.239)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)?

不要紧张,输入yes就好,然后会看到:

1
Hi <em>username</em>! You've successfully authenticated, but GitHub does not provide shell access.

设置你的账号信息

现在你已经可以通过SSH链接到GitHub了,还有一些个人信息需要完善的。

Git会根据用户的名字和邮箱来记录提交。GitHub也是用这些信息来做权限的处理,输入下面的代码进行个人信息的设置,把名称和邮箱替换成你自己的,名字必须是你的真名,而不是GitHub的昵称。

1
2
$ git config --global user.name "你的名字"
$ git config --global user.email "your_email@youremail.com"

好了,你已经可以成功连接GitHub了。

新建仓库

在自己的账号下,新建一个repository(仓库)。创建成功后,可根据一下界面操作。

GitRepo

创建版本库

版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来, 每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以”还原”。具体步骤已经完整在上图中展示,下面具体说明。

第一步:首先,选择一个合适的地方,创建一个空目录:

1
2
$ mkdir yourRepo 
$ cd yourRepo

第二步:通过git init命令把这个目录变成Git可以管理的仓库

1
2
$ git init  
Initialized empty Git repository in ./yourRepo/.git/

./yourRepo目录下 新建一个README.txt文件,内容为”hello github”

第三步:用命令git add告诉Git,把文件添加到仓库:

$ git add README.txt  

第四步:用命令git commit 把文件提交到仓库:

$ git commit -m "hello github"

第五步:输入远程地址

$ git remote add origin git@github.com:yourName/yourRepo.git

或者

$ git remote add origin https://github.com/yourName/yourRepo.git 

如果显示 fatal: remote origin already exists,使用如下命令:

1
2
$ git remote rm origin
$ git remote add origin git@github.com:yourName/yourRepo.git

第六步:上传到github

如果该仓库是第一次进行push,输入

$ git push -u origin master

如果已经传输过,此处只是更新,只需输入:

$ git push

提交成功后就可以进入github查看自己的项目了。

git push命令会将本地仓库推送到远程服务器。git pull命令则相反。
注:首次提交,先git pull下,修改完代码后,使用git status可以查看文件的差别。

忽略文件

一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。 来看一个实际的例子:

1
2
3
$ cat .gitignore
*.[oa]
*~

第一行告诉 Git 忽略所有以 .o.a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。 第二行告诉 Git 忽略所有以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。 要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。

文件 .gitignore 的格式规范如下:

  • 所有空行或者以 开头的行都会被 Git 忽略。

  • 可以使用标准的 glob 模式匹配。

  • 匹配模式可以以(/)开头防止递归。

  • 匹配模式可以以(/)结尾指定目录。

  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹配 a/z, a/b/za/b/c/z等。

我们再看一个 .gitignore 文件的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# no .a files
*.a

# but do track lib.a, even though you're ignoring .a files above
!lib.a

# only ignore the TODO file in the current directory, not subdir/TODO
/TODO

# ignore all files in the build/ directory
build/

# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt

# ignore all .pdf files in the doc/ directory
doc/**/*.pdf

Tip: GitHub 有一个十分详细的针对数十种项目及语言的 .gitignore 文件列表,你可以在 https://github.com/github/gitignore 找到它.

某些push错误的情况

错误1: 新建仓库push出错

有时候对新建的仓库进行push操作,会出现上传失败的情况。
通常出现这种情况的原因,是新建的仓库往往会有一个文件Readme.md文件,而本地仓库中没有这个文件,也就是说本地仓库与服务器端仓库没有实现同步。所以将这个Readme.md文件pull到本地,然后再commit提交,应该就没有问题了。

1
$ git pull origin master  //该指令必须先执行,否则到push的时候会报错,因为在github端已经有一个文件了:README.md,会提示远程仓库和本地仓库有不一致的地方

错误2: 本地仓库与远程仓库不一致

在 push 操作的时候遇到下述错误:

1
2
3
4
5
error: 无法推送一些引用到 'git@github.com:upcAutoLang/BackgroundSplit-OpenCV.git' 
提示:更新被拒绝,因为远程仓库包含您本地尚不存在的提交。这通常是因为另外
提示:一个仓库已向该引用进行了推送。再次推送前,您可能需要先整合远程变更
提示:(如 'git pull ...')。
提示:详见 'git push --help' 中的 'Note about fast-forwards' 小节。

出现该情况的原因可能是之前在上传时创建的.git文件被删除或者修改,也可能是其他人在 Github 上提交过代码。

解决方案:

1 强行上传:

$ git push -u origin master

2 尽量先同步 Github 上的代码到本地,在上面更改之后再上传。

$ git pull origin master 
$ git push -u origin master

必须保证每个文件夹下不能再有除了刚才生成的.git文件夹之外的.git,否则上传后那个文件夹将会是空文件夹,因为.git文件夹是包含连接信息的。和别的会有冲突。

错误3: 上传文件太大

出现错误:this exceeds Github’s file size limit of 100MB

千万不要用这种办法,会把本地的文件删除!!!太坑了

1
2
3
4
5
6
7
$ git filter-branch --force --index-filter"git rm --cached --ignore-unmatch 文件名及详细路径"  --prune-empty--tag-name-filter cat -- --all

$ git commit --amend –CHEAD

再执行一次

$ git push -u origin master。

解决办法参考下文git reflog

常用Git命令

Git add, Git commit 添加错文件 撤销

Git add 添加多余文件

git add 如果添加了错误的文件的话

撤销操作

1
2
3
git status 先看一下add 中的文件 
git reset HEAD 如果后面什么都不跟的话 就是上一次add 里面的全部撤销了
git reset HEAD XXX/XXX/XXX.java 就是对某个文件进行撤销了

Git commit 错误

如果不小心 弄错了 git add后 , 又 git commit 了。
先使用

1
2
3
4
5
git log 查看节点 
commit xxxxxxxxxxxxxxxxxxxxxxxxxx
Merge:
Author:
Date:

然后

1
git reset commit_id

PS:还没有 push 也就是 repo upload 的时候

1
2
git reset commit_id (回退到上一个 提交的节点 代码还是原来你修改的) 
git reset –hard commit_id (回退到上一个commit节点, 代码也发生了改变,变成上一次的)

commit后最佳撤销办法git reflog

首先使用 git reflog 命令查看操作记录:

1
2
3
4
5
6
7
8
$ git reflog
c1c1b21 HEAD@{0}: commit (amend): add blank line to index.html
9ff821d HEAD@{1}: commit: add blank line to index.html
b078331 HEAD@{2}: commit: no more commit!
b86e902 HEAD@{3}: commit: so many commit
77e6ce9 HEAD@{4}: commit: this is another commit
ccde039 HEAD@{5}: commit: this is a commit
a49dcf4 HEAD@{6}: clone: from ssh://liux@xxx.xx.xx.xxx:29418/git_test.git

看到 amend 操作之前的最后一个操作就是 HEAD@{1}.
现在可以用 git reset 将当前分支的 HEAD 指向 HEAD@{1}, 即可达到撤销 amend 的目的:

1
2
3
4
5
6
7
8
9
10
$ git reset --soft HEAD@{1}
$ git status
On branch master
Your branch is ahead of 'origin/master' by 5 commits.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: index.html

随即使用 git status 查看状态, 发现 amend 的内容已经被撤销 (到工作区) 了.

如果想撤销到暂存区, 就用 git reset --soft HEAD@{1} .

如果想干掉这个修改, 就用 git reset --hard HEAD@{1} .

这和 git reset 操作 commit 的情形是一样的.

如果一个 commit 被 amend 了多次, 也可以用这种方法撤销到任意一次 amend 处:

1
2
3
4
5
6
7
$ git reflog
937fd53 HEAD@{0}: commit (amend): add blank line to index.html
7589755 HEAD@{1}: commit (amend): add blank line to index.html
f7ade82 HEAD@{2}: commit (amend): add blank line to index.html
c1c1b21 HEAD@{3}: commit (amend): add blank line to index.html
9ff821d HEAD@{4}: commit: add blank line to index.html
$ git reset --soft HEAD@{2}

可以看出, 不止是 amend 操作, 其他操作也可以用这种方法进行撤销.

Push 之后发现错误

如果要是提交了以后,可以使用 git revert

还原已经提交的修改

此次操作之前和之后的commit和history都会保留,并且把这次撤销作为一次最新的提交

最好不要用这种办法,会把本地的文件删除!!!虽然可以再revert回来

1
2
3
4
git revert HEAD 撤销前一次 commit 
git revert HEAD^ 撤销前前一次 commit
git revert commit-id (撤销指定的版本,撤销也会作为一次提交进行保存)
git revert是提交一个新的版本,将需要revert的版本的内容再反向修改回去,版本会递增,不影响之前提交的内容。

查看、添加、提交、删除、找回,重置修改文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
git help <command> # 显示command的help

git show # 显示某次提交的内容 git show $id

git co -- <file> # 抛弃工作区修改

git co . # 抛弃工作区修改

git add <file> # 将工作文件修改提交到本地暂存区

git add . # 将所有修改过的工作文件提交暂存区

git rm <file> # 从版本库中删除文件

git rm <file> --cached # 从版本库中删除文件,但不删除文件

git reset <file> # 从暂存区恢复到工作文件

git reset -- . # 从暂存区恢复到工作文件

git reset --hard # 恢复最近一次提交过的状态,即放弃上次提交后的所有本次修改

git ci <file> git ci . git ci -a # 将git add, git rm和git ci等操作都合并在一起做                                    git ci -am "some comments"

git ci --amend # 修改最后一次提交记录

git revert <$id> # 恢复某次提交的状态,恢复动作本身也创建次提交对象

git revert HEAD # 恢复最后一次提交的状态

查看文件diff

1
2
3
4
5
6
7
8
9
10
11
git diff <file> # 比较当前文件和暂存区文件差异 git diff

git diff <id1><id2> # 比较两次提交之间的差异

git diff <branch1>..<branch2> # 在两个分支之间比较

git diff --staged # 比较暂存区和版本库差异

git diff --cached # 比较暂存区和版本库差异

git diff --stat # 仅仅比较统计信息

查看提交记录

1
2
3
4
5
6
7
git log git log <file> # 查看该文件每次提交记录

git log -p <file> # 查看每次详细修改内容的diff

git log -p -2 # 查看最近两次详细修改内容的diff

git log --stat #查看提交统计信息

Mac上可以使用tig代替diff和log,brew install tig

Git 本地分支管理

查看、切换、创建和删除分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
git br -r # 查看远程分支

git br <new_branch> # 创建新的分支

git br -v # 查看各个分支最后提交信息

git br --merged # 查看已经被合并到当前分支的分支

git br --no-merged # 查看尚未被合并到当前分支的分支

git co <branch> # 切换到某个分支

git co -b <new_branch> # 创建新的分支,并且切换过去

git co -b <new_branch> <branch> # 基于branch创建新的new_branch

git co $id # 把某次历史提交记录checkout出来,但无分支信息,切换到其他分支会自动删除

git co $id -b <new_branch> # 把某次历史提交记录checkout出来,创建成一个分支

git br -d <branch> # 删除某个分支

git br -D <branch> # 强制删除某个分支 (未被合并的分支被删除的时候需要强制)

分支合并和rebase

1
2
3
4
5
git merge <branch> # 将branch分支合并到当前分支

git merge origin/master --no-ff # 不要Fast-Foward合并,这样可以生成merge提交

git rebase master <branch> # 将master rebase到branch,相当于: git co <branch> && git rebase master && git co master && git merge <branch>

Git补丁管理(方便在多台机器上开发同步时用)

1
2
3
4
5
git diff > ../sync.patch # 生成补丁

git apply ../sync.patch # 打补丁

git apply --check ../sync.patch #测试补丁能否成功

Git暂存管理

1
2
3
4
5
6
7
git stash # 暂存

git stash list # 列所有stash

git stash apply # 恢复暂存的内容

git stash drop # 删除暂存区

Git远程分支管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
git pull # 抓取远程仓库所有分支更新并合并到本地

git pull --no-ff # 抓取远程仓库所有分支更新并合并到本地,不要快进合并

git fetch origin # 抓取远程仓库更新

git merge origin/master # 将远程主分支合并到本地当前分支

git co --track origin/branch # 跟踪某个远程分支创建相应的本地分支

git co -b <local_branch> origin/<remote_branch> # 基于远程分支创建本地分支,功能同上

git push # push所有分支

git push origin master # 将本地主分支推到远程主分支

git push -u origin master # 将本地主分支推到远程(如无远程主分支则创建,用于初始化远程仓库)

git push origin <local_branch> # 创建远程分支, origin是远程仓库名

git push origin <local_branch>:<remote_branch> # 创建远程分支

git push origin :<remote_branch> #先删除本地分支(git br -d <branch>),然后再push删除远程分支

Git远程仓库管理

1
2
3
4
5
6
7
git remote -v # 查看远程服务器地址和仓库名称

git remote show origin # 查看远程服务器仓库状态

git remote add origin git@ github:robbin/robbin_site.git # 添加远程仓库地址

git remote set-url origin git@ github.com:robbin/robbin_site.git # 设置远程仓库地址(用于修改远程仓库地址) git remote rm <repository> # 删除远程仓库

创建远程仓库

1
2
3
4
5
6
7
8
9
10
11
12
13
git clone --bare robbin_site robbin_site.git # 用带版本的项目创建纯版本仓库

scp -r my_project.git git@ git.csdn.net:~ # 将纯仓库上传到服务器上

mkdir robbin_site.git && cd robbin_site.git && git --bare init # 在服务器创建纯仓库

git remote add origin git@ github.com:robbin/robbin_site.git # 设置远程仓库地址

git push -u origin master # 客户端首次提交

git push -u origin develop # 首次将本地develop分支提交到远程develop分支,并且track

git remote set-head origin master # 设置远程仓库的HEAD指向master分支

也可以命令设置跟踪远程库和本地库

1
2
3
git branch --set-upstream master origin/master

git branch --set-upstream develop origin/develop

Git remote

要 参与任何一个 Git 项目的协作,必须要了解该如何管理远程仓库.远程仓库是指托管在网络上的项目仓库,可能会有好多个,其中有些你只能读,另外有些可以写.同他人协作开发某 个项目时,需要管理这些远程仓库,以便推送或拉取数据,分享各自的工作进展.管理远程仓库的工作,包括添加远程库,移除废弃的远程库,管理各式远程库分 支,定义是否跟踪这些分支,等等.本节我们将详细讨论远程库的管理和使用.
  查看当前的远程库

  要查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字.在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库:

  $ git clone git://github.com/schacon/ticgit.git

  Initialized empty Git repository in /private/tmp/ticgit/.git/

  remote: Counting objects: 595, done.

  remote: Compressing objects: 100% (269/269), done.

  remote: Total 595 (delta 255), reused 589 (delta 253)

  Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done.

  Resolving deltas: 100% (255/255), done.

  $ cd ticgit

(1)git remote 不带参数,列出已经存在的远程分支

  $ git remote

  origin

(2)git remote -v | –verbose 列出详细信息,在每一个名字后面列出其远程url

此时, -v 选项(译注:此为 –verbose 的简写,取首字母),显示对应的克隆地址:

  $ git remote -v

  origin git://github.com/schacon/ticgit.git如果有多个远程仓库,此命令将全部列出.比如在我的 Grit 项目中,可以看到:

  $ cd grit

  $ git remote -v

  bakkdoor git://github.com/bakkdoor/grit.git

  cho45 git://github.com/cho45/grit.git

  defunkt git://github.com/defunkt/grit.git

  koke git://github.com/koke/grit.git

  origin 这样一来,我就可以非常轻松地从这些用户的仓库中,拉取他们的提交到本地.请注意,上面列出的地址只有 origin 用的是 SSH URL 链接,所以也只有这个仓库我能推送数据上去(我们会在第四章解释原因).

  添加远程仓库

  要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname] [url]:

  $ git remote

  origin

  $ git remote add pb git://github.com/paulboone/ticgit.git

  $ git remote -v

  origin git://github.com/schacon/ticgit.git

  pb git://github.com/paulboone/ticgit.git现在可以用字串 pb 指代对应的仓库地址了.比如说,要抓取所有 Paul 有的,但本地仓库没有的信息,可以运行 git fetch pb:

  $ git fetch pb

  remote: Counting objects: 58, done.

  remote: Compressing objects: 100% (41/41), done.

  remote: Total 44 (delta 24), reused 1 (delta 0)

  Unpacking objects: 100% (44/44), done.

  From git://github.com/paulboone/ticgit

  * [new branch] master -> pb/master

  * [new branch] ticgit -> pb/ticgit

现在,Paul 的主干分支(master)已经完全可以在本地访问了,对应的名字是 pb/master,你可以将它合并到自己的某个分支,或者切换到这个分支,看看有些什么有趣的更

Reference

以上内容分别转载自

[1] git命令之git remote的用法

[2] GitHub入门教程

[3] Ubuntu环境如何上传项目到GitHub网站?

[4] 如何使用Git上传项目代码到github

[5] git add , git commit 添加错文件 撤销

[6] 撤销 git commit –amend

CATALOG
  1. 1. Introduction
    1. 1.1. Git 的三种状态
    2. 1.2. 记录每次更新到仓库
  2. 2. Github 的使用
    1. 2.1. 本地SSH Keys的设置
    2. 2.2. 添加SSH Key到GitHub
    3. 2.3. 设置你的账号信息
    4. 2.4. 新建仓库
    5. 2.5. 创建版本库
  3. 3. 忽略文件
  4. 4. 某些push错误的情况
    1. 4.1. 错误1: 新建仓库push出错
    2. 4.2. 错误2: 本地仓库与远程仓库不一致
    3. 4.3. 错误3: 上传文件太大
  5. 5. 常用Git命令
    1. 5.1. Git add, Git commit 添加错文件 撤销
      1. 5.1.1. Git add 添加多余文件
      2. 5.1.2. Git commit 错误
      3. 5.1.3. commit后最佳撤销办法git reflog
      4. 5.1.4. Push 之后发现错误
    2. 5.2. 查看、添加、提交、删除、找回,重置修改文件
    3. 5.3. Git 本地分支管理
    4. 5.4. Git补丁管理(方便在多台机器上开发同步时用)
    5. 5.5. Git暂存管理
    6. 5.6. Git远程分支管理
    7. 5.7. Git远程仓库管理
  6. 6. Git remote
  7. 7. Reference