这些是 2011 年 8 月 3 日在 Max-Planck Institute of molecular Cell Biology and Genetics 举行的 Git 研讨会的笔记。
什么是版本控制系统,我为什么要关心?
版本控制系统是一个保存项目多个修订版本的数据库。修订版包括
- 文件名和内容(不包括生成的文件)及其目录结构
- 作者
- 提交者
- 作者日期
- 提交日期
- 描述(提交消息)导致此修订的更改内容,通常分为第一行(主题)和更详细的其余部分(正文)
- 零个、一个或多个指向当前修订版本之前的修订版本的指针
在 Git 中,提交 指的是修订。
版本控制通常有助于:
- 轻松备份
- 轻松检索特定修订
- 文档(谁做了什么、何时以及为什么?)
- 文档(我该怎么做……?)
- 轻松同步(保持最新状态,集成多个开发人员/机器之间的更改)
- 有效地找到引入回归(又名错误)的变化
动手实践
初始设置:
- 设置用户名:
git config --global user.name "Howard Carter" git config --global user.email howard@egyptian-antiquities-service.com - 设置编辑器(如果您不喜欢 vi)
git config --global core.editor wordpad第一步:
- 初始化存储库
git init - 添加内容(Subversion 用户注意:
git add添加内容,而不仅仅是文件名)git add hello-world.txt - 犯罪
git commit注意事项:
- 所有修改的文件应在调用
git commit之前添加 - 由于添加的文件已暂存以供提交,因此命令
git stage是git add的同义词 - 利用
git status输出 - 使用
.gitignore文件 - 添加签核(AKA S-O-B)
git init创建 .git/,其中存储了所有存储库的文件git config访问.git/config、~/.gitconfig和/etc/gitconfig
什么是差异?
在提交之前,最好先看看将要提交哪些修改。查看它们的一种模式是让 Git 显示 diff。每个修改的文件的 diff 由以下部分组成:
1.以diff --git开头的伪命令行
- 一行描述先前修订版,以
---开头 - 一行描述下一个修订版本,以
+++开头 - 一名或多名以
@@ -<begin line>,<line count> +<begin line>,<line count>开头的帅哥 - 相应的行块,以空格开头,用于表示上一个版本和下一个版本中的行,减号表示仅在前一个版本中的行(删除的行),加号表示仅在下一个版本中的行(添加的行)。修改后的行将显示为已删除和已添加。
动手实践
- 查看差异:
git diff - 查看颜色差异:
git diff --color - 更改颜色差异的默认值:
git config --global diff.color auto关于 Git 数据模型的一句话(以及如何引用对象)
参见Git for computer scientists。
- 一切都是对象
- 每个对象都有一个类型
- 每个对象都有一个名称,该名称是通过单向函数(散列函数 SHA-1)根据类型和内容计算得出的
- 这是一个 40 位十六进制数字
- 每个对象都是不可变的(更改某些内容会更改名称)。
- 普通文件被编码为 blob
- 目录被编码为树
- 修订被编码为提交
为了便于使用,除了长名称(40 个十六进制字符,相当笨拙但精确)之外,还可以通过以下方式引用提交
- 简称
HEADHEAD~<n>
动手实践
- 检查版本历史记录
git log - 以图形方式检查版本历史记录
gitk - 通过差异检查版本历史记录
git log -p - 检查最新 5 个版本的差异
git log -p -5 - 仅检查一次提交
git show HEAD~5 - 查看涉及一组特定文件/目录的所有提交
git log README注意:为了消除开始提交和文件之间的歧义,请在提交和/或选项和文件/目录之间放置
--,例如git log HEAD -5 -- doc
什么是分支?为什么我需要它们?
分支是指向提交图的命名指针。主分支称为“main”(Subversion 的 trunk,Mercurial 的 default)。由于分支只是指针,因此很容易创建它们。
在分支上提交时会推进该指针(如果您需要无法推进的内容,则需要使用 tags)。
注意:分支名称必须简单,即不包含空格或通配符(尽管减号和下划线也可以)。
分支可用于按主题组织更改集。另请比较Fiji’s tutorial on topic branches。
动手实践
- 创建分支
git checkout -b my-new-branch - 切换到另一个分支
git checkout main - 查看所有(本地)分支(当前分支以星号为前缀)
git branch - 切换回上一个分支
git checkout @{-1}对于 Git 来说,“分布式”是什么意思?
到目前为止,存储库位于工作目录本地。但 Git 还可以与多个其他存储库同步。
通常,有一个指定的“主存储库”。如果您想从给定存储库初始化工作目录,请使用git clone。
主存储库通常不需要工作目录,在这种情况下,它被称为裸存储库。
动手实践
- 克隆存储库
git clone git://github.com/git/hello-world - 从 USB 磁盘或文件服务器克隆存储库
git clone /path/to/hello-world - 在文件服务器上设置主存储库
git init --bare --shared=group /path/to/fileserver/my.gitGit 的合并概念(这个“索引”到底是什么?)
当与其他人或主题分支一起工作时,更改(包括其完整的提交历史记录)需要集成到另一个分支中,通常是main。这种集成称为合并。
为了执行合并,文件版本被放入暂存区域(索引),并且所有不重叠的更改都会自动解决。重叠(读作:矛盾)的更改未得到解决,而是标记为合并冲突。
请参阅斐济页面 Git Conflicts,了解如何解决合并冲突的详细说明。
动手实践
- 初始化并提交一个文件,例如hello.txt
echo Hello > hello.txt git add hello.txt git commit -m initial - 初始化一个新分支并修改hello.txt
git checkout -b tut-anch-amun echo Boooh > hello.txt git add hello.txt git commit -m "On branch" - 切换回旧分支,修改hello.txt
git checkout @{-1} echo Hi > hello.txt git add hello.txt git commit -m "On original branch" - 合并
git merge tut-anch-amun什么是转发日志?他们能如何帮助我?
我们之前查看了提交历史记录。但每个存储库都有其自己的历史;例如,昨天中午,具有特定修订的特定分支是当前分支。这存储在引用日志中(为了空间效率,引用日志不是永久可用的,而是在某个阶段被修剪)。
您可以通过将 @{<number>} 或 @{<date>} 附加到分支名称或 HEAD 来访问引用日志。
动手实践
- 查看五分钟前当前的修订版本
git show HEAD@{5.minutes.ago} - 查看转发历史记录
git log -g藏品是什么?
有时需要存储所有修改并返回到干净状态,但保持修改可访问。这是使用 stash 完成的。
注意:stash 是一个特殊的伪分支,位于 refs/stash 中。他们的历史记录在转发日志中。
动手实践
- 进行更改并隐藏它
echo Shalom > hello.txt git stash - 把它拿回来
git stash apply - 仅存储尚未使用
git add添加的更改echo Howdy > hello.txt git add hello.txt echo Hey hey > hello.txt git stash -k - 获取隐藏更改的列表
git stash list - 隐藏自定义消息
git stash save This is my description - 从存储中删除最新的更改
git stash pop访问对象数据库的部分内容
查看提交的主要方法是使用 git show。它可以显示标签、提交、树和 blob。
要访问有关提交的更多信息,请使用参数--pretty=fuller。
对于更底层的访问,请使用git cat-file。
动手实践
- 显示原始提交消息以及差异
git show --pretty=raw HEAD - 显示提交对应的顶级树
git show HEAD: - 显示一个斑点
git show HEAD:Documentation/README - 对提交的低级访问
git cat-file commit HEADGit 中的“checkout”、“reset”有什么含义?
我们已经看到checkout可以在分支之间切换,甚至可以初始化新分支。
不幸的是,checkout也是从其他分支选择文件版本而不切换分支的命令。因此,选择的文件版本会自动添加,即为下一次提交暂存。
要取消暂存更改,可以使用 reset 命令(不带参数,它会重置 HEAD 当前知道的所有文件)。
可以进一步说服reset命令不仅重置索引(暂存区域),还重置工作目录。
动手实践
- 从另一个分支选择文件版本
git checkout other-branch README - 取消所有更改,即将所有文件从“待提交”状态恢复为“已修改”
git reset - 删除所有更改(如
git stash,但不存储更改)git reset --hardGit 的“远程存储库”概念
除了我们克隆的存储库之外,还可以使用 git remote 命令链接其他存储库。此类存储库称为“远程存储库”或简称为“远程”。
我们克隆的存储库称为 origin。
与远程存储库的交互是使用
git fetch,远程存储库分支的本地副本,包括所有必需的对象(但要聪明地避免获取我们已经拥有的对象)和git push,将远程存储库的分支更新为本地分支的状态。
远程分支的本地副本位于特定的命名空间中,refs/remotes/<name>。例如,名为 origin 的远程的 main 分支将存储在 refs/remotes/origin/main 中。如果明确的话,也可以将其称为 origin/main。
注意:您需要确保不要在同一工作目录的存储库中混合两个不同的项目。 Git 会很乐意从任何地方获取到本地存储库,即使它没有意义。
注意:获取和合并有一个快捷方式:git pull。如果您从远程分支的本地副本创建新分支,您甚至可以对其进行设置,以便 git pull 无需进一步参数即可从正确的远程获取并合并正确的分支:git checkout --track origin/cool-feature
动手实践
- 添加遥控器
git remote add hello git://github.com/git/hello-world - 从远程获取
git fetch hello - 列出远程分支的所有本地副本
git branch -r - 推一个分支
git push origin main - 推送当前分支
git push origin HEAD - 推送到名称与本地名称不同的分支
git push origin my-new-branch:main - 从远程存储库中删除分支
git push --delete origin blabla-branch流行的公共存储库托管商
如果您需要公共存储库,您可以使用 http://github.com/、http://code.google.com/、http://sourceforge.net/、http://repo.or.cz/ 以及其他一些库。通常,您拥有相当数量的存储空间,但问题是您的版本控制项目必须是开源的。
值得庆幸的是,所有上述托管服务商都支持 gitweb,这是一个用于查看历史记录的 Web 界面。
动手实践
让我们浏览http://github.com/git/hello-world并检查历史
高级主题
-
别名
-
重新定位
-
采摘樱桃
-
部分分期
-
交互式结帐
-
标签(简单、带注释、签名)
-
平分
-
责备
-
git apply -
git diff --color-words -
归档
-
脚本编写(管道/瓷器)
-
钩子
-
差异过滤器
-
与svn交互
-
与 Mercurial 交互
-
涂抹/清洁过滤器
-
合并驱动程序
-
差异驱动程序
-
重命名处理
链接
- 主页:http://git-scm.com/
- Windows 版 Git:http://code.google.com/p/msysgit/
- MacOSX 版 Git http://code.google.com/p/git-osx-installer/
- 底层数据模型概述:http://eagain.net/articles/git-for-computer-scientists/
- 斐济的主题分支教程:https://fiji.sc/wiki/index.php/ Git_topic_branches
- ProGit 书:http://progit.org/
- 最受欢迎的存储库托管商:https://github.com/
- 原始存储库托管者:http://repo.or.cz/
- Git 维基:https://git.wiki.kernel.org/index.php/Main_Page