如果我们现在运行一个 git log 命令,我们将看到前面的提交之前的一个新提交。
$ git log --oneline 11b7712 Revert "File with three lines" b764644 File with three lines 7c709f0 File with two lines 9ef9173 File with one line
这里是工作目录中这个文件当前的内容:
$ cat <filename> Line 1 Line 2
图 3 revert 操作之后
恢复或重置如何选择?
为什么要优先选择 revert 而不是 reset 操作?如果你已经将你的提交链推送到远程仓库(其它人可以已经拉取了你的代码并开始工作),一个 revert 操作是让他们去获得更改的非常友好的方式。这是因为 Git 工作流可以非常好地在分支的末端添加提交,但是当有人 reset 分支指针之后,一组提交将再也看不见了,这可能会是一个挑战。
当我们以这种方式使用 Git 工作时,我们的基本规则之一是:在你的本地仓库中使用这种方式去更改还没有推送的代码是可以的。如果提交已经推送到了远程仓库,并且可能其它人已经使用它来工作了,那么应该避免这些重写提交历史的更改。
总之,如果你想回滚、撤销或者重写其它人已经在使用的一个提交链的历史,当你的同事试图将他们的更改合并到他们拉取的原始链上时,他们可能需要做更多的工作。如果你必须对已经推送并被其他人正在使用的代码做更改,在你做更改之前必须要与他们沟通,让他们先合并他们的更改。然后在这个侵入操作没有需要合并的内容之后,他们再拉取最新的副本。
你可能注意到了,在我们做了 reset 操作之后,原始的提交链仍然在那个位置。我们移动了指针,然后 reset 代码回到前一个提交,但它并没有删除任何提交。换句话说就是,只要我们知道我们所指向的原始提交,我们能够通过简单的返回到分支的原始链的头部来“恢复”指针到前面的位置:
git reset <sha1 of commit>
当提交被替换之后,我们在 Git 中做的大量其它操作也会发生类似的事情。新提交被创建,有关的指针被移动到一个新的链,但是老的提交链仍然存在。
变基
现在我们来看一个分支变基。假设我们有两个分支:master 和 feature,提交链如下图 4 所示。master 的提交链是 C4->C2->C1->C0 和 feature 的提交链是 C5->C3->C2->C1->C0 。
图 4:master 和 feature 分支的提交链
如果我们在分支中看它的提交记录,它们看起来应该像下面的这样。(为了易于理解,C 表示提交信息)
$ git log --oneline master 6a92e7a C4 259bf36 C2 f33ae68 C1 5043e79 C0 -
$ git log --oneline feature 79768b8 C5 000f9ae C3 259bf36 C2 f33ae68 C1 5043e79 C0
我告诉人们在 Git 中,可以将 rebase 认为是 “将历史合并”。从本质上来说,Git 将一个分支中的每个不同提交尝试“重放”到另一个分支中。
因此,我们使用基本的 Git 命令,可以变基一个 feature 分支进入到 master 中,并将它拼入到 C4 中(比如,将它插入到 feature 的链中)。操作命令如下:
$ git checkout feature $ git rebase master -
First, rewinding head to replay your work on top of it... Applying: C3 Applying: C5
完成以后,我们的提交链将变成如下图 5 的样子。
图 5:rebase 命令完成后的提交链
接着,我们看一下提交历史,它应该变成如下的样子。
$ git log --oneline master 6a92e7a C4 259bf36 C2 f33ae68 C1 5043e79 C0 -
$ git log --oneline feature c4533a5 C5 64f2047 C3 6a92e7a C4 259bf36 C2 f33ae68 C1 5043e79 C0
(编辑:ASP站长网)
|