《Pro Git》笔记

一、什么是Git

版本控制系统:
版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
采用版本控制系统可以将选定的文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。

版本控制方式:
1复制整个项目目录:简单、容易犯错。
2本地版本控制系统:大多都是采用某种简单的数据库来记录文件的历次更新差异。

让在不同系统上的开发者协同工作?
3集中化的版本控制系统:一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。

整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。
4分布式版本控制系统:客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来,包括完整的历史记录。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。

和其他版本控制系统的差别:
Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方式。 从概念上来说,其它大部分系统以文件变更列表的方式存储信息,这类系统(CVS、Subversion、Perforce、Bazaar 等等)将它们存储的信息看作是一组基本文件和每个文件随时间逐步累积的差异(它们通常称作基于差异(delta-based)的版本控制)。

Git 不按照以上方式对待或保存数据。反之,Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个快照流。

在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。

Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。若你在传送过程中丢失信息或损坏文件,Git 就能发现。Git 用以计算校验和的机制叫做 SHA-1散列(hash,哈希)。 这是一个由40个十六进制字符(0-9和a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来。

执行的 Git 操作,几乎只往 Git 数据库中 添加 数据。 你很难使用 Git 从数据库中删除数据,也就是说 Git 几乎不会执行任何可能导致文件不可恢复的操作。

二、Git的三种状态和三个区域

Git 有三种状态,你的文件可能处于其中之一:
已修改(modified):已修改表示修改了文件,但还没保存到数据库中。
已暂存(staged):已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
已提交(committed):已提交表示数据已经安全地保存在本地数据库中。

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

暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。

Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。包括本地分支和本地分支跟踪的远程分支,但是不包括远程仓库的分支,git fetch就是将远程仓库的分支同步到本地分支跟踪的远程分支。

三、Git的使用

基本的 Git 工作流程
1在工作区中修改文件。
2add:将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
3commit:提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。
4push:推送到远程仓库

两种获取 Git 项目仓库的方式
1.将尚未进行版本控制的本地目录转换为 Git 仓库;
进入项目目录
git init:创建子目录.git,Git 仓库中所有的必须文件。
git add :指定所需的文件来进行追踪,
git commit:进行初始提交。

2.从其它服务器克隆一个已存在的 Git 仓库。
git clone :默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。

git add 命令
1可以用它开始跟踪新文件,
2或者把已跟踪的文件放到暂存区,
3还能用于合并时把有冲突的文件标记为已解决状态等。
将这个命令理解为“精确地将内容添加到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。

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

查看提交历史
git log 会按时间先后顺序列出所有的提交(commit),最近的更新排在最上面。 正如你所看到的,这个命令会列出每个提交的 SHA-1校验和、作者的名字和电子邮件地址、提交时间以及提交说明。

撤消操作
运行带有–amend 选项的提交命令来重新提交:

git commit -m 'initial commit
git add forgotten_file
git commit --amend

这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。
当你在修补最后的提交时,与其说是修复旧提交,倒不如说是完全用一个新的提交替换旧的提交,理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。

取消暂存的文件

git reset HEAD CONTRIBUTING.md

撤消对文件的修改
撤消修改——将它还原成上次提交时的样子

git checkout -- CONTRIBUTING.md

git checkout —  是一个危险的命令。 你对那个文件在本地的任何修改都会消失Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。
在 Git 中任何已提交的东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用–amend 选项覆盖的提交也可以恢复。 然而,任何你未提交的东西丢失后很可能再也找不到了。

查看远程仓库
git remote 命令:列出你指定的每一个远程服务器的简写。 如果你已经克隆了自己的仓库,那么至少应该能看到 origin ——这是 Git 给你克隆的仓库服务器的默认名字。

远程仓库中抓取与拉取

git fetch:访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。
必须注意 git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。

git pull :自动抓取后合并该远程分支到当前分支。 这或许是个更加简单舒服的工作流程。默认情况下,git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或其它名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。

推送到远程仓库
git push origin master :当你想分享你的项目时,必须将其推送到上游。 当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字),那么运行这个命令就可以将你所做的备份到服务器。
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先抓取他们的工作并将其合并进你的工作后才能推送。

四、Git 的分支

什么是分支?
其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master。 在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 master 分支会在每次提交时自动向前移动。
提交对象:包含一个指向上次提交对象(父对象)的指针、指向前述树对象的指针和所有提交信息
树对象:记录着目录结构和 blob 对象索引
blob 对象:保存的文件快照(每一个被改动文件的哈希索引和数据)

分支创建
使用 git branch 命令,在当前所在的提交对象上创建一个指针。
HEAD 指针:
指向当前所在的本地分支(译注:将 HEAD 想象为当前分支的别名)。在本例中,你仍然在 master 分支上。因为 git branch 命令仅仅创建一个新分支,并不会自动切换到新分支中去。
分支切换:
git checkout 命令切换到一个已存在的分支,HEAD 指向切换到的分支。HEAD分支随着提交操作自动向前移动。
在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支。

分支合并
基于 master 分支的紧急问题分支 hotfix branch,可以运行你的测试,确保你的修改是正确的,然后将 hotfix 分支合并回你的 master 分支来部署到线上。 你可以使用 git merge 命令来达到上述目的。
由于你想要合并的分支 hotfix 所指向的提交 C4 是你所在的提交 C2 的直接后继,因此 Git 会直接将指针向前移动。换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做“快进(fast-forward)”。

解决问题追踪系统中的#53问题。 想要新建一个分支并同时切换到那个分支iss53上。已经修正了 #53问题,并且打算将你的工作合并入 master 分支。 为此,你需要合并 iss53 分支到 master 分支,这和之前你合并 hotfix 分支所做的工作差不多。 你只需要检出到你想合并入的分支,然后运行 git merge 命令。

遇到冲突时的分支合并
有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对#53问题的修改和有关 hotfix 分支的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突。此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。
任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。 Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。 出现冲突的文件会包含一些特殊区段。

git fetch:
Git 的 clone 命令会为你自动将其命名为 origin,拉取它的所有数据,创建一个指向它的 master 分支的指针,并且在本地将其命名为 origin/master。 Git 也会给你一个与 origin/master 分支在指向同一个地方的本地 master 分支,这样你就有工作的基础。
如果要与给定的远程仓库同步数据,运行git fetch。 从远程仓库中抓取本地没有的数据,并且更新本地数据库,移动 origin/master 指针到更新之后的位置。

git pull:
检出一个本地分支会自动创建所谓的“跟踪分支”(它跟踪的分支叫做“上游分支”)。 跟踪分支是与远程分支有直接关系的本地分支。 如果在一个跟踪分支上输入 git pull,Git 能自动地识别去哪个服务器上抓取、合并到哪个分支。
当克隆一个仓库时,它通常会自动地创建一个跟踪 origin/master 的 master 分支。 然而,如果你愿意的话可以设置其他的跟踪分支,或是一个在其他远程仓库上的跟踪分支,又或者不跟踪 master 分支。

git fetch和git pull:
当 git fetch 命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容。 它只会获取数据然后让你自己合并。 然而,有一个命令叫作 git pull ,在大多数情况下它的含义是一个 git fetch 紧接着一个 git merge 命令。 如果有一个像之前章节中演示的设置好的跟踪分支,不管它是显式地设置还是通过 clone 或 checkout 命令为你创建的,git pull 都会查找当前分支所跟踪的服务器与分支,从服务器上抓取数据然后尝试合并入那个远程分支。
由于 git pull 的魔法经常令人困惑,所以通常单独显式地使用 fetch 与 merge 命令会更好一些。

来源:https://git-scm.com/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值