转载请注明出处:Alvin Lee的博客:http://blog.csdn.net/lihaoweiV


git rebase 命令的功能很强大, 在《git 权威指南》一书里,改变提交(commit)的顺序,书中教了一种很复杂的方法,运用了git reset ... git cherry-pick...等等命令。

但如果用git rebase 命令,则一下就搞定。

以下面的例子来讲解一下git rebase 的其中一个用法,

************************************* 改变提交(commit) 的顺序 ****************************************

git log一下查看commit log:

现有:

commit A  hello    (这里用字母ABCDE代替了那串很长的Hash code)

commit B  hi

commit C  how are you

commit D  i am fine

commit E  bye

现在想将D换到B之前,即 A, D, B, C, E,

我们可以用 git rebase -i [commit号] 命令,  因为现在要改变D的位置, 所以我们要rebase到commit E那里, 具体命令为:

git rebase -i E

按回车后会出现下面的文字

  pick A hello
  pick B  hi
  pick C  how are you
  pick D  i am fine

  pick E  bye
 
  # Rebase 23350be..92c4c19 onto 23350be   (以下部分可能会根据情况不一样而不同)
   #
   # Commands:
   #  p, pick = use commit
  #  r, reword = use commit, but edit the commit message
  #  e, edit = use commit, but stop for amending
  #  s, squash = use commit, but meld into previous commit
  #  f, fixup = like "squash", but discard this commit's log message
  #
  # If you remove a line here THAT COMMIT WILL BE LOST.
  # However, if you remove everything, the rebase will be aborted.
  #



要将D弄到B前面,只需将上面的pick语句的位置换一下,换成如下

  pick A hello

  pick D  i am fine
  pick B  hi
  pick C  how are you
  pick E  bye


然后保存退出,如果你确定位置置换了之后不会发生冲突,就会出现以下字样表示成功了

successfully rebased and updated refs/heads/[你的branch名].


你再git log一下,看看现在的顺序为

commit A  hello 

commit D  i am fine

commit B  hi

commit C  how are you

commit E  bye


当然, 你可以用此方法置换成任何你想要的顺序,但你得先确定,换位后不会发生冲突。如果有冲突,是不会出现successfully的字样的。



以下再说另一种git rebase的用法

**************** 修改提交(非置顶的提交)内容(包括标题,作者,代码等)并更新提交 ************

现有

commit A hello

commit B hi

commit C how are u

commit D bye


我想修改commit C的代码 和标题,但我又不想用git reset 命令这么麻烦,

这里也可以用git rebase -i [commit号] 命令

具体为:

git rebase -i D ,       因为我要修改C,所以我要rebase 到C的前一个commit,即D。

按回车后仍然会看到像上面一样的文字


  pick A hello
  pick B  hi
  pick C  how are you
  pick D  bye

 
  # Rebase 23350be..92c4c19 onto 23350be   (以下部分可能会根据情况不一样而不同)
   #
   # Commands:
   #  p, pick = use commit
  #  r, reword = use commit, but edit the commit message
  #  e, edit = use commit, but stop for amending
  #  s, squash = use commit, but meld into previous commit
  #  f, fixup = like "squash", but discard this commit's log message
  #
  # If you remove a line here THAT COMMIT WILL BE LOST.
  # However, if you remove everything, the rebase will be aborted.
  #


这里将C 前面的pick 改为edit ,即

  pick A hello
  pick B  hi
  edit C  how are you
  pick D  bye

然后保存退出,就会出现以下字样:

You can amend the commit now, with


        git commit --amend


Once you are satisfied with your changes, run


        git rebase --continue


现在你想修改什么内容? 


如果你想修改commit 的标题, 备注, 作者签名等信息,请用

git commit --amend 命 令

例如,我要将commit C的标题 改为 Hello, I m Alvin Lee. 用上述命令修改完之后保退出去,

然后再用git rebase --continue使你的修改生效。


如果你发现commit C代码有bug,想修改那个bug,例如driver/alvin.c 里有个bug, 则直接打开该文件:

int main(void)

{

prinntk("Hello I am Alvin Lee!\n")

return 1;

}


将错误处修改:

printk("Hello I am Alvin Lee!\n");

保存退出。 用git add 命令将你的修改添加到暂存区(index),

再用git rebase --continue命令使你的修改生效,

如果没有冲突, 则一切OK!

现在用git log -p [commit号] 命令看一下,

int main(void)

{

printk("Hello I am Alvin Lee!\n");

return 1;

}

错误被修改过来了!



******************************************* 更多用法, 且听下回分解 ***************************************************






1.出现情况的背景:

   当你提交的代码后,管理员发现,您的代码不能提交到服务器上,主要原因在于,你的commit 中和服务器中的有些commit不再同一时间轴上,即:你的有些commit要插入到服务器中的某些commit之间,这样就会造成代码的冲突。所以这个时候就要使用git rebase。

 假如,你平时使用的分支叫 new ,然后在这个分支上你刚提交过几个commit。

 做法:

1.新建一个分支,并且代码和服务器中代码同步

   git checkout origin/v2.0 -b temp  

2.为了保证新建的temp分支代码是最新的,可以多执行下面一步

  git pull

3.当你新建分支后,系统会自动checkout到temp分支上,此时

  git checkout  new

4.合并代码,并整理

  git rebase  temp  //会将temp分支的代码合并过来,并按照提交的顺序排序

5.  因为顺序是重新整理的,所以肯定会出现冲突

6.解决冲突,最后 git add * ,但不许要git commit

7.解决后,执行 git rebase --continue

8.重新提交代码: git push for-*


注意:如果要对某些代码的commit重新整理

1. 可以记住某个commit号

2. git rebase -i commit号

3. 会显示一个整理提交的界面,有很多参数,e。p。等等

4.将前面的参数改为e。则wq保存后,系统会自动让你重新修改commit内容

5.修改完成后,再git push for-*

==============================

 


rebase

假设你现在基于远程分支"origin",创建一个叫"mywork"的分支。

$ git checkout -b mywork origin

现在我们在这个分支做一些修改,然后生成两个提交(commit).

$ vi file.txt
$ git commit
$ vi otherfile.txt
$ git commit
...

但是与此同时,有些人也在"origin"分支上做了一些修改并且做了提交了. 这就意味着"origin"和"mywork"这两个分支各自"前进"了,它们之间"分叉"了。

在这里,你可以用"pull"命令把"origin"分支上的修改拉下来并且和你的修改合并;结果看起来就像一个新的"合并的提交"(merge commit):

但是,如果你想让"mywork"分支历史看起来像没有经过任何合并一样,你也许可以用 git rebase:

$ git checkout mywork
$ git rebase origin

这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新到最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。

当'mywork'分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除. (请查看git gc)

现在我们可以看一下用合并(merge)和用rebase所产生的历史的区别:

在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:

$ git rebase --continue

这样git会继续应用(apply)余下的补丁。

在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。

$ git rebase --abort

gitcast:c7-rebase

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐