《Pro Git》学习笔记

1.Git远程模型示意图

git_model

Remote:远程仓库
Repository:本地仓库
Index:暂存区
workspace:当前工作区

2.取得Git仓库

2.1 初始化新仓库

git init

2.2 从现有仓库克隆

git clone git://github.com/xxx/xxx.git [dirName]

3.记录每次更新到仓库

3.1 文件状态变化周期

lifecircle

3.2 检查当前文件的状态

git status

3.3 跟踪新文件

git add

3.4 更新已放到暂存区但是之后被修改的文件

git add

3.5 查看已暂存和未暂存的更新

git diff 查看工作区与暂存区的差异
git diff –cached 已暂存的文件与上次提交之间的差别

3.6 提交更新

git commit 或者 git commit -m “具体说明”

3.7 跳过暂存区直接更新

git commit -a -m “更新说明”

3.8 删除文件

git rm <文件名>

如果删除之前已经修改过并且放到了暂存区,那么使用-f选项来强制删除暂存区中的文件。该参数用来防止误删文件后丢失修改的内容。

3.9 移除对文件的跟踪但是不删除文件

git rm –cached <文件名>

删除的时候如果在“*”号前面加“\”那么就会递归删除当前目录下所有匹配的文件,例如:git rm *.tmp。

3.10 移动文件

git mv <文件1> <文件2> 相当于先删除文件1,然后增加文件2

4.查看提交的历史

git log

常见用法:

4.1 展开内容差异

git log -p -2 (-p 展开每次提交的内容差异,用-2表示仅显示最近的两次更新)

4.2 仅显示简要的增改行数统计

git log –stat

4.3 指定格式展示提交历史

git log –pretty=oneline (将每个提交放在一行显示,还有short、full、fuller可以用)

4.4 定制记录格式

git log –pretty=format:”%h – %an, %ar : %s” ,常用格式占位符的写法及意义为:

选项 说明
%H 提交对象(commit)的完整哈希字串
%h 提交对象的简短哈希字串
%T 树对象(tree)的完整哈希字串
%t 树对象的简短哈希字串
%P 父对象(parent)的完整哈希字串
%p 父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s 提交说明
4.5 限制筛选条件

git log –[n|since|after|until|author|committer] ,选项说明:

选项 说明
-(n) 仅显示最近的 n 条提交
–since, –after 仅显示指定时间之后的提交
–until, –before 仅显示指定时间之前的提交
–author 仅显示指定作者相关的提交
–committer 仅显示指定提交者相关的提交

5、撤销操作

5.1 修改最后一次提交

git commit -m “initial commit”
git add forgotten_file
git commit –amend

5.2 取消已暂存的文件

git reset HEAD <文件名>

5.3 取消对文件的修改

git checktout — <文件名>

6.远程仓库

6.1 查看当前远程仓库

git remote [-v]

6.2 添加远程仓库

git remote add <远程仓库名> <远程仓库地址>

6.3 从远程仓库抓取数据

git fetch <远程仓库名>

如果是克隆了一个仓库,此命令会自动将远程仓库归于 origin 名下。所以,git fetch origin 会抓取从你上次克隆以来别人上传到此远程仓库中的所有更新(或是上次 fetch 以来别人提交的更新)。有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。

如果设置了某个分支用于跟踪某个远端仓库的分支(参见下节及第三章的内容),可以使用 git pull 命令自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。在日常工作中我们经常这么用,既快且好。实际上,默认情况下git clone 命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)。所以一般我们运行git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中的当前分支。

6.4 推送数据到远程仓库

git push [远程仓库名] [分支名]

6.5 查看远程仓库信息

git remote show [远程仓库名]

6.6 远程仓库的删除和重命名

git remote rename <旧仓库名> <新仓库名>

7.打标签

在发布某个软件版本的时候使用Git对某一时间点上的版本打上标签。

7.1 查看已有标签

git tag [-l <标签模式>]

例如:git tag -l ‘v1.4.2.*’

7.2 新建标签

Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。轻量级标签就像是个不会变化的分支,实际上它就是个指向特 定提交对象的引用。而含附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。

含附注的标签:
git tag -a <标签名> [-m <标签说明>]

-a选项指定含附注类型,-m选项指定标签说明。

轻量级标签:
git tag <标签名>

7.3 签署标签

利用私钥和GPG来签署标签。
git tag -s <签名> [-m <标签说明>]

7.4 验证标签

git tag -v <标签名>

需要有签署者的公钥存放在keyring中。

7.5 后期加注标签

git tag -v <标签名> <校验和前几位>

7.6 分享标签

git push <远程仓库名> <标签名>

8.分支理论

commit对象指向包含各个文件blob对象索引的tree对象。Git分支的本质是个指向commit对象的可变指针,Git使用master作为分支的默认名字。Git通过创建一个新的分支指针来创建新的分支:git branch <分支名>。

HEAD是一个指向正在工作中的本地分支的指针,可以将其当做当前分支的别名。

8.1 将HEAD切换到其他分支

git checktout <分支名>

切换分支的时候最好保持一个清洁的工作区域。

8.2 分支的新建与切换

git checkout -b <新分支名>
相当于:
git branch <新分支名>
git checkout <新分支名>

8.3 分支的合并

假设要将分支hotfix合并到分支master,首先检出master分支,然后合并分支。
git checkout master
git merge hotfix

8.4 删除分支

git branch -d <分支名>

8.5 查看所有分支

git branch [-v|–merged|–on-merged]
-v选项用来查看各分支最后一个commit的信息,–merged用来查看哪些分支已经并入当前分支。

8.6 利用分支来进行开发工作

长期分支(master):例如master分支,保留完全稳定的代码,稳定的分支总是比较老旧。
开发分支(develop):与master平行的专门用于后续开发或者稳定性测试的分支。
特性分支(topic):短期的用来实现单一特性的分支。
branches

8.7 远程分支

远程分支(remote branch)是对远程仓库中分支的索引。它们是无法移动的本地分支,只有在Git进行网络交互时才会更新。远程分支一般用<远程仓库名>/<分支名>这样的形式来表示。

一次Git克隆会建立本地分支master和远程分支origin/master,它们都指向origin/master分支的最后一次提交。

(1)同步远程服务器上的数据:git fetch origin。该命令首先找到origin服务器,从上面获取数据然后把origin/master的指针移动到最新的位置。

(2)推送本地分支:git push <远程仓库名> <本地分支名>[:<远程分支名>]。如果不指定<远程分支名>,那么会使用与本地分支相同的名字。

(3)值得注意的是,即使用fetch操作获取了新的远程分支,任然无法在本地编辑远程仓库的分支,如果要把远程分支的内容合并到当前分支,可以使用:git merge <远程仓库名>/<远程分支名>。

(4)如果想要自己的可编辑分支,可以在远程分支的基础上分化出一个新的分支来:git checkout -b <新分支名> <远程仓库名>/<远程分支名>。从远程分支中checkout出来的本地分支称为跟踪分支,跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入 git push,Git会自行推断该向哪个服务器的哪个分支推送数据。同样在跟踪分支里运行 git pull 会获取远程索引并把它们的数据都合并到本地分支中来。

(5)删除远程分支:git push <远程仓库名> :<远程分支名>

8.8 分支的衍合

把一个分支整合到另一个分支的办法有两种:merge 和 rebase(暂译为衍合)。merge的原理是将两个分支最新的快照以及二者最新的共同祖先进行三方合并,然后生成一个新的提交对象。rebase的原理是:假设有两个分支 experiment 和 master,experiment是我们要衍合的分支。先回到两者的共同祖先,依据 experiment 后续的历次提交产生一系列补丁,然后以基底分支 master 的最后一个提交对象为新的出发点,逐个应用之前准备好的补丁文件,最后会产生一个新的合并提交对象,改写experiment的提交历史。其命令表示为:

git checkout experiment
git rebase master
experiment

rebase 和 merge 最后得到的快照内容是相同的,但 rebase 能够提供更为简洁的提交历史。一般我们使用衍合的目的,是想要得到一个能在远程分支上干净应用的补丁 — 比如某些项目你不是维护者,但想帮点忙的话,最好用衍合:先在自己的一个分支里进行开发,当准备向主项目提交补丁的时候,根据最新的 origin/master 进行一次衍合操作然后再提交,这样维护者就不需要做任何整合工作(译注:实际上是把解决分支补丁同最新主干代码之间冲突的责任,化转为由提交补丁的人来解决),只需根据你提供的仓库地址作一次快进合并,或者直接采纳你提交的补丁。

衍合也可以放到其他分支进行,并不一定非得根据分化之前的分支。以图 3-31 的历史为例,我们为了给服务器端代码添加一些功能而创建了特性分支 server,然后提交 C3 和 C4。然后又从 C3 的地方再增加一个 client 分支来对客户端代码进行一些相应修改,所以提交了 C8 和 C9。最后,又回到 server 分支提交了 C10。
3_31
图 3-31. 从一个特性分支里再分出一个特性分支的历史。

假设在接下来的一次软件发布中,我们决定先把客户端的修改并到主线中,而暂缓并入服务端软件的修改(因为还需要进一步测试)。这个时候,我们就可以把基于 server 分支而非 master 分支的改变(即 C8 和 C9),跳过 server 直接放到 master 分支中重演一遍,但这需要用 git rebase 的 –onto 选项指定新的基底分支 master:

$ git rebase –onto master server client
这好比在说:“取出 client 分支,找出 client 分支和 server 分支的共同祖先之后的变化,然后把它们在 master 上重演一遍”。是不是有点复杂?不过它的结果如图 3-32 所示,非常酷(译注:虽然 client 里的 C8, C9 在 C3 之后,但这仅表明时间上的先后,而非在 C3 修改的基础上进一步改动,因为 server 和 client 这两个分支对应的代码应该是两套文件,虽然这么说不是很严格,但应理解为在 C3 时间点之后,对另外的文件所做的 C8,C9 修改,放到主干重演。):
3_32
图 3-32. 将特性分支上的另一个特性分支衍合到其他分支。

现在可以快进 master 分支了(见图 3-33):

$ git checkout master
$ git merge client
3_33

图 3-33. 快进 master 分支,使之包含 client 分支的变化。

现在我们决定把 server 分支的变化也包含进来。我们可以直接把 server 分支衍合到 master,而不用手工切换到 server 分支后再执行衍合操作 — git rebase [主分支] [特性分支] 命令会先取出特性分支 server,然后在主分支 master 上重演:

$ git rebase master server
于是,server 的进度应用到 master 的基础上,如图 3-34 所示:
3_34
图 3-34. 在 master 分支上衍合 server 分支。

然后就可以快进主干分支 master 了:

$ git checkout master
$ git merge server
现在 client 和 server 分支的变化都已经集成到主干分支来了,可以删掉它们了。最终我们的提交历史会变成图 3-35 的样子:

$ git branch -d client
$ git branch -d server
3_35

图 3-35. 最终的提交历史

rebase的风险:一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行rebase操作。

《大数据时代》读书笔记

数据已经成为一种商业资本,一项重要的经济投入,可以创造新的经济利益。事实上,通过对海量数据进行分析,我们可以获得巨大价值的产品或服务,或者深刻的洞见。

大数据时代的思维变革:

(1)不是随机样本,而是全体数据:在大数据时代的第一个转变就是利用所有数据,而不再仅仅依靠一小部分数据。采样分析的精确性随着采样随机性的增加而大幅提高,但与样本数量的增加关系不大。因此样本选择的随机性比样本数量更加重要。大数据的方法不采用随机分析法,而是采用所有数据,即样本=总体。

(2)追求数据的混杂性而不是精确性:大数据为了扩大数据规模允许不精确。大数据的简单算法比小数据的复杂算法更加有效。大数据要求我们接受纷繁性,放弃对精确性的追求,在大数据时代我们无法获得精确性。

(3)大数据追求相关关系而非因果关系:通过监控一个现象的良好的关联物,相关关系可以帮助我们捕捉现在和预测未来。大数据的相关关系分析法更加准确、更快,而且不易受传统思维模式和特定领域里隐含的固有偏见的影响。建立在相关关系分析法上基础上的预测是大数据的核心。

大数据时代的商业变革:

(1)一切皆可量化:量化是数据化的核心。我们要的是数据化而不是数字化。数据化是指一种把现象转变为可制表分析的量化形式的过程。数字化指的是把模拟数据转换为0和1换算表示的二进制码。

有了大数据的帮助,我们不再会将世界看作世界是一连串我们认为或是自然或是社会的现象,我们会意识到本质上世界是由信息构成的。将世界看作信息,看作可以理解的数据海洋,为我们提供了一个从未有过的审视现实的视角。它是一种可以渗透到所有生活领域的世界观。

(2)数据的绝大部分价值都隐藏在表面之下:数据的价值不仅限于特定用途,它可以为同一目的而被多次使用,也可以用于其他目的。数据的基本用途是为信息的收集和处理提供依据。不同于物质的东西,数据的价值不会随着它的使用而减少,而是可以不断地被处理。

数据的创新包括:数据的再利用(采集用户的搜索数据判断用户的偏好或发展趋势)、重组数据(多个数据集的总和重组在一起时比单个数据集更有价值)、可扩展数据(使得某种方式收集的单一数据集有多种不同的用途)、数据的折旧值(随着时间推移,大多数数据都会失去一部分基本用途但潜在价值依然强大)、数据废气(使用用户在网上留下的数字轨迹,如在线交互痕迹,来改善旧服务)、开放数据(开放政府数据让私营部门和社会大众访问)。

公司所持有的数据可视为公司的无形资产。

(3)数据、技术与思维的三足鼎立:大数据价值链的构成为大数据采集掌控、大数据挖掘技术、大数据思维。现今我们处在大数据时代的早期,思维和技能是最有价值的。但最终大部分的价值还是必须从数据本身中挖掘。大数据公司的多样性表明了数据价值的转移。随着数据价值转移到数据拥有者手上,传统的商业模式也就被颠覆了。

未来行业专家和技术专家的光芒都会因为统计数学家和数据分析家的出现而变暗。因为后者不受旧观念的影响,能够聆听数据发出的声音。

大数据决定企业的竞争力。规模很重要,大规模的公司拥有大量数据以及采集更多数据的能力,而小规模公司则更加灵活,因此中型企业将会逐渐消亡。

大数据时代的管理变革:

(1)让数据主宰一切隐忧:大数据的核心思想是用规模剧增来改变现状,这会给我们带来更多威胁。

在大数据时代,不管是告知与许可(很多数据在收集时并无意用作其他意图,而最终却产生了很多创新的用途)、模糊化(有意识的模糊化可能起到反作用)还是匿名化(大数据促进了内容的交叉检验),这三大隐私保护策略都失效了。

大数据被滥用于因果分析可能导致罪责的判定是基于对个人未来的预测。进行个人罪责推定需要行为人选择某种特定的行为,他的选择是造成这个行为的原因。而大数据并不是建立在因果关系基础上的,而是相关关系!所以大数据绝不可以用来进行罪责推定!

不能盲目信任数据的力量和潜能而忽略了它的局限性。

(2)责任与自由并举的信息管理:大数据时代要借助限制信息滥用的规范而不是最初的审查来防止其泛滥。要想保护个人隐私就需要个人数据处理器对其政策和行为承担更多的责任。

个人隐私保护从个人许可到让数据使用者承担责任:为了实现数据二次运用的优势与过度披露所带来的风险,监管机制可以决定不同种类的个人数据必须删除的时间。再利用的时间框架则取决于数据内在风险和社会价值观的不同。公司可以利用数据的时间更长,但相应的必须为其行为承担责任以及负有特定时间之后删除个人数据的义务。我们还可以开发新的技术促进隐私保护。如“差别隐私”:故意将数据模糊处理,促使对大数据库的查询不能显示精确结果。

大数据时代,个人可以并应该为他们的行为而非倾向负责。

在依据大数据技术作重大决策时必须保证特定防护措施的到位:(a)公开原则。用来进行预测分析的数据和算法必须公开。(b)公正原则。具备由第三方专家公证的可靠、有效的算法系统。(c)可反驳原则。明确提出个人可以对其预测进行反驳的具体方式。(d)确保对人的评判依据真实行为而非大数据分析。

大数据的运作超出我们正常理解范围。为了防止大数据的预测、运算法则和数据库变得不透明、不可解释、不可追踪,大数据需要被检测并保持透明度,当然还有使这两项得以实现的新型专业技术和机构,大数计算法师将会崛起。

为了保护极具竞争力的大数据市场,必须防止垄断。政府也应该公布其数据。

结束语:

凡事过去,皆为序曲:大数据意味着我们永远受困于过去的行为,这些行为在预知我们下一步动作的预测过程中与我们作对,即我们将永远无法逃避已经发生的事。

如果所有人都诉诸数据和工具,那时人类的无法预测性直觉、冒险精神、意外和错误等反而可能发挥出重大作用。在大数据时代,包括创意、直觉、冒险精神和知识野心在内的人类特性的培养显得尤为重要,因为进步正是源自我们的独创性。

大数据提供的不是最终答案,只是参考答案,为我们提供暂时的帮助,以便等待更好的方法和答案出现。这也提醒我们在使用这个工具的时候,应当怀有谦恭之心,铭记人性之本。