① 如何在svn系统中使用git
操作步骤:
你需要:
1.安装 git 和 git-svn
2.创建工作目录:mkdir strigi
3.初始化git工作目录:
4.找到项目的某个提交 (你可以通过 cia版本控制 去获得). 警告: 命令git-log 会从这个版本开始显示项目的版本历史。
5.执行命令git-svn fetch -rREVISION,REVISION 就是刚才获得的那个版本号。
6.更新工作目录:git-svn rebase,现在你就可以在这个项目中使用git作为版本控制了。
要保持工作目录更新,可以执行:
git-svn rebase
你可以用下面的命令将更改提交到svn服务器:
git-svn dcommit
通过这种方式,所有的git提交都会“转换”成相应的svn命令。
解决git-svn rebase的问题
在加入新东西之前,你也许会在同步主开发树的时候体验到一些问题。实际上,你在执行git-svn
rebase之前还必须提交所有的本地修改(使用git-commit命令)。
有时候这并不合理,因为你的更改也许还没有准备好提交(还没有完成、测试或者验证这写代码)。不过别担心,git对此也有一个官方的解决方案,只需下面的步骤:
先把你的改动保存起来,使用命令:git-stash
更新工作副本,使用命令:git-svn rebase,这跟平时一样
恢复保存起来的改动,使用命令:git-stash apply
清除“保存”,使用命令:git-stash
clear。第1步之后,所有未提交的改动在工作副本上都看不到了,因而你可以执行rebase命令,不会有任何问题。
② git命令之git merge 和 git rebase的区别
git merge是用来合并两个分支的。
# 将b分支合并到当前分支
git merge b
git cherry-pick可以选择某一个分支中的一个或几个commit(s)来进行操作。例如,假设我 们有个稳定版本的分支,叫v2.0,另外还有个开发版本的分支v3.0,我们不能直接把两个分支合并,这样会导致稳定版本混乱,但是又想增加一个v3.0 中的功能到v2.0中,这里就可以使用cherry-pick了。
# 先在v3.0中查看要合并的commit的commit id
git log
# 假设是 commit
# 切到v2.0中
git check v2.0
# 合并commit
git cherry-pick
git rebase有点类似git merge,但是两者又有不同,打个比方,你有两个抽屉A和B,里面都装了衣服,现在想把B中的衣服放到A中,git merge是那种横冲直撞型的,拿起B就倒入A里面,如果满了(冲突)再一并整理;而git rebase就很持家了,它会一件一件的从B往A中加,会根据一开始放入的时间顺序的来加,如果满了你可以处理这一件,你可以继续加,或者跳过这一件,又 或者不加了,把A还原。所以merge适合那种比较琐碎的,简单的合并,系统级的合并还是用rebase吧。
专业的区别请移步到这里合并和衍合
# 合并b
git rebase b
# 处理完冲突继续合并
git rebase –continue
# 跳过
git rebase –skip
# 取消合并
git rebase –abort
③ SourceTree 合并分支时几个选项是什么意思
SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端,同时也是Mercurial和Subversion版本控制系统工具。支持创建、克垄提交、push、pull 和合并等操作。
git入门五(分支合并冲突和衍合)
分支合并冲突的处理
合并分支的冲突时在不同的分支中修改了同一个文件的同一部分,程序无法把两份有差异的文件合并,这时候需要人为的干预解决冲突。当前处于master 分支,当dev 分支和master 分支对相当部分test1.txt 都做了修改,当合并dev 分支的时候,合并会出现分支冲突如下:查询当前工作区的状态可以显示那些文件发生合并冲突,任何包含未解决冲突的文件都会以未合并(ummerged)的状态列出,git 会加入标准冲突解决标记,可以通过手工定位来解决这些冲突。可以看大 =======隔开以上部分就是当前活动分支,也是合并的基准分支(head 指向的master分支),======分隔符以下的是dev分支中的内容。解决冲突的办法无非是二者选其一或者由你亲自整合到一起。比如你可以两部分内容合并成 一部分内容。
$ git branch
dev
* master
testing
$ git merge dev
Auto-merging test1.txt
CONFLICT (content): Merge conflict in test1.txt
Automatic merge failed; fix conflicts and then commit the result.
$ git status
# On branch master
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: test1.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ notepad test1.txt
<<<<<<< HEAD
now this is bug fix branch
=======
this is branch merge conflict problem
>>>>>>> dev
同时还可以用图形化界面的工具来处理分支,git mergetool 命令会调用时当前系统配置的合并工具。合并完成后可以查询状态git status 来确认所有冲突都已经解决。如果冲突解决都已完成,可以把合并后的内容提交到暂存区,可以用git commit 完成这次合并提交。针对冲突合并,需要写好注释说明,后续查看会更加简单方便。
$ git commit -m "master merge dev branch"
[master 05a2f29] master merge dev branch
1 files changed, 4 insertions(+), 1 deletions(-)
分支的管理
git branch 是查询当前所有分支的清单,*号的表示当前的活动分支,也就是当前所在的分支。也就是说如果现在有提交更新,当前的工作分支master 分支或向前移动。若要看各个分支最后一个提交对象的新,可以通过git branch -v 来查看。
$ git branch
dev
* master
testing
$ git branch -v
dev be70ec8 dev
* master 05a2f29 master merge dev branch
testing 0c8f2de testing branch change
在所有分支清单中,可以筛选出那些与当前分支尚未合并,通过参数--merge 可以筛选出那些分支在当前分支的上游,这些分支只需要通过fast-forward 移动指正就可以移动当当前最后提交给对象。--no-merged 可以查看还位和当前分支合并的分支。如dev分支和当前分支还未合并。如果以前是无效的分支,可以通过git branch -d 删除制定的分支。
$ git branch --merged
* master
testing
$ git branch --no-merged
dev
$ git branch -d testing
Deleted branch testing (was 0c8f2de).
长期分支
git只是简单的三方合并分支的特性,所以在脚长的一段时间内,把多个分支合并到一个分支或者同时拥有多发分支进行开发。由于每个分支都有特定的任务,随着开发的推进,随时可以把某个特性分支合并到其它分支中。需求使用git 的开发者都喜欢用这种方式开发,一般来说仅仅在master 分支保留稳定的代码,就是已经发布或者经过测试的代码。与此同时,你可以同时拥有多个开发分支。每个开发分支都有特定的任务。如还有一个叫develop 的平行分支,专门拥有后续的开发,仅拥有稳定性的测试。一旦到达某种稳定的状态就可以合并到master 分支。如果有其它特性的短缺分支能够通过测试,并且不会引如更多错误后,就可以并到主干master分支中。等待下一次发布。
随着提交对象的不断右移指针,稳定分支总是在提交历史中落后一大截,而且前言分支总是比较靠前。稳定分支总是滞后,经过测试比较稳定的对象或者集合才被合并到稳定的分支上。这样可以维护不同层次的稳定。
特性分支
在任何规模的项目中可以使用特性分支(topic).一个特性是指一个短期的,用来实现单一特性与其相关的工作分支,你可以在以前版本中从未做过类似的这样事情,因为创建和合并分支的消耗太大。然而在git中,一天之内创建,删除和合并多个分支是常见的事情。在创建特性分支后,你可以提交合并到主干分支,然后删除他,该技术让你迅速且完全进行语境切换。因为你的工作分散在不同的流水性力,每个分支力改变都和他的目标特性相关。你可以把做出的改变保持在特性分支几分钟。几天甚至几个月。等他们成熟以后再合并。而不用在乎他们建立的顺序和进度。
一般分支都是在本地。大部分都是本地分支。这一点很重要。当前使用合并分支的时候,一切都在你的git 仓库中进行的,完全不与服务器交互。只有当你有固定的分支或者分享需要和其它合作伙伴共享的时候,才需要推送到中心服务器。
远程分支:
remote branch 是对远程仓库中的分支的索引。他们是无法移动本地分支。只有在git进行网络交互时才会更新。远程分支就是书签,提醒着你上次链接远程仓库时上面各个分支的位置。 我们用仓库名/分支名 这样的形式表示远程分支。比如我们想想上次同 origin 仓库进行通讯时master 分支的样子。就应该查看origin/master 分支。如果你和同伴一起修复某个问题。他们推送一个iss53分支到远程仓库。虽然你可能也有一个本地的iss53分支,但指向服务器上最新的更新的英是origin/iss53分支。
假如团队中心服务器git地址:git.ourcompany.com.。如果你从这里克隆,git会自动在为你将次远程仓库吗命名为origin。并下载其中的数据,建立一个指向它的master分支指针。在本地命名为Origin/master。但你无法再本地更改数据,接着git建立一个属于你自己本地的master分支。始于origin上master分支相同的位置。如下图
如果你在本地master 分支做了些改动。与此同时本地分支向前推进。只要本地没有向远程服务器推送,origin/master 分支指针任然保持在原位不会移动。
在本地工作同时有人向远程仓库推送内容会让历史开始分流。可以允许git fethch origin 来同步远程服务器上的数据到本地。该命令首先找到origin 是哪个服务器。从上面获取你未拥有的数据。更新你本地的数据库。然后把Origin/master的指针移动到他最新的位置上。
如果有多个远程分支的项目是如果进行工作的。我们假设你还有另外一个内部使用的远程服务器。通过git remote add 命令吧它加为当前项目的远程分支之一。我们把它命名为teamtone,以便代替完整的git url。
现在把另外一个远程服务器添加为远程仓库了,现在可以用git fetch teamtone 来获取小组服务器你还没有的数据,由于当前服务器的内容是origin服务器上的子集,git不会下载任何数据。而只是简答创建一个名为teamone/master 的远程分支。指向teamone 服务器上master 分支所有在的提交对象 31b3e 如下图:现在你在本地就有了一个指向teamone 的索引。
推送本地分支
要想和其它人分享某个本地的分支,你需要把它推送到一个拥有些权限的远程仓库。你创建的本地分支部会因为你的写入操作而被自动同步到你引入的远程服务器上,你需要明确的执行推送分支的操作。换句话说,对于无意分享的分支,你尽管保留私人分支好了。而只推送那些协同工作要用到的特性分支。如果有个交severfix 的分支需要和他人一起开发,可以运行git push (远程仓库名) 分支名。
$ git push origin serverfix
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:andy/test.git
* [new branch] serverfix -> serverfix
git 自动把serverfix 分支名扩展为refs/heads/serverfix:refs/heads/serverfix,意思是“取出我在本地的serverfix分支,推送到远程仓库的serverfix分支中区,一般在同一分支上可以省略, git push origin serverfix:serverfix,还可以把本地分支推送到远程不同的分支。可以用已经存在的新远程分支或新的远程分支。
当你再次从远程获取服务器上数据的时候,同伴会获取到origin/serverfix 和 origin/newfix 的分支,并指向服务器上serverfix 所指向的版本。在fetch操作下载好新的远程分支之后。你任然无法再本地编辑远程仓库中的分支。换句话说你不会有一个新的serverfix 分支。有的只是一个你无法移动的Origin/serverfix指针。你如果需要把该远程分支的内容合并到当前分支,可以运行git merge origin/serverfix ,如果想要一份自己的serverfix来开发。可以在远程分支的基础上分化一个新的分支来。这会切换到新的serverfix 的本地分支。其内容同远程分支 origin/serverfix 一致。这样可以继续开发了。
$ git push origin serverfix:newfix
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:andyi/test.git
* [new branch] serverfix -> newfix
$ git fetch origin
remote: Counting objects: 19, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 17 (delta 6), reused 16 (delta 5)
Unpacking objects: 100% (17/17), done.
From github.com:andyi/test
* [new branch] dev -> origin/dev
894ed8b..37b40ce master -> origin/master
跟踪远程分支
从远程分支checkout 出来的本地分支。称为跟踪(tracking branch),跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入git push,git 会自行推断应该向那个服务器的那个分支推送数据。同样,在这些分支里运行git pull 会回去远程索引,并把它们的数据合并到本地分支中。
在克隆仓库时,git 通常会自创建一个名master 的分支来跟踪,这正是git push 和 git pull 一开始就能正常工作的原因。当然,你可以随心所欲设定其为跟踪分支,比如在origin 上除了master 之外的其它分支。刚才我们已经开到了这样的一个例子。 git checkout -b 分支名 远程名/分支名, 还可以用 --track 选项。 如果本地分支和远程分支的名称不一样,可以本地分支换个名称。
$ git checkout -b serv origin/serverfix
Branch serv set up to track remote branch serverfix from origin.
Switched to a new branch 'serv'
$ git branch
master
* serv
serverfix
删除远程分支
如果不再需要摸个远程分支了,比如搞定某个特性并合并进了远程的master 分支(或任何其他存放稳定的代码分支),可以用这个命令 git push 远程名:分支名。如果运行这个命令,服务器上的分支就没了,git puhs 远程名 本地分支:远程分支 语法,如果省略本地分支。那就是等提前空白然后把它变成远程分支。
分支的衍和
把一个分支中的修改整合到另一个分支的办法由两种:merge 和 rebase(翻译为衍合)。
基本的衍合操作,当开发进程分叉到两个不同的分支,有各自提交了更新。最简单的整合方式是合并merege 命令。他会把两者共同的祖先ac631f6进行三方合并。并合后产生一个结果就是两条分的合并点。
其实除了合并以外,还有另外一个选择,可以把7599941产生变化的补丁在4632de基础上重新打一遍。在git 里着叫衍合(rebase),有了rebase命令,就可以在把在一个分只里提交的改变移动到另一个分支重方一遍。他们的原理是回到两个分支最近共同的祖先。根据当前分支(也就是要进行衍合的分支)后续历次提交的对象在这里分支只有一个提交。生产一系列文件补丁,然后基地分支(也就是主干分支master 的最后一个提交对象为新的出发点,逐个应用之前准备好的补丁文件,最后会生产一个新的合并提交对象。从而改写需要衍合分支的提交历史。使他成为master 分支的直接下游。
④ git merge和rebase的区别
merge和rebase的区别
处理冲突的方式:
使用merge命令合并分支,解决完冲突,执行git add .和git commit -m'fix conflict'。这个时候会产生一个commit。
使用rebase命令合并分支,解决完冲突,执行git add .和git rebase --continue,不会产生额外的commit。这样的好处是‘干净’,分支上不会有无意义的解决分支的commit。
git pull和git pull --rebase区别:git pull做了两个操作分别是‘获取’和合并。所以加了rebase就是以rebase的方式进行合并分支,默认为merge。
⑤ git reset rebase和 revert的区别
git revert 放弃某次提交
git revert 之前的提交仍会保留在git log中,而此次撤销会做为一次新的提交。
git reset 是回滚到某次提交
git reset --soft
此次提交之后的修改会被退回到暂存区
git reset --hard
此次提交之后的修改不做任何保留,git status干净的工作区。
git rebase 当两个分支不在一条直线上,需要执行merge操作时,使用该命令操作。
该命令执行时极有可能显示merge失败,如下图1,使用git
diff命令查看冲突内容,手动
修改冲突,git add filename,表示冲突已解决,再执行git
rebase --continue,继续rebase。
图1
⑥ merge和rebase的区别
merge 是一个合并操作,会将两个分支的修改合并在一起,默认操作的情况下会提交合并中修改的内容
merge 的提交历史忠实地记录了实际发生过什么,关注点在真实的提交历史上面
rebase 并没有进行合并操作,只是提取了当前分支的修改,将其复制在了目标分支的最新提交后面
rebase 的提交历史反映了项目过程中发生了什么,关注点在开发过程上面
merge 与 rebase 都是非常强大的分支整合命令,没有优劣之分,使用哪一个应由项目和团队的开发需求决定
merge 和 rebase 还有很多强大的选项,可以使用 git help <command> 查看
使用 merge 时应考虑是采用 --no-ff 默认操作,生成一个对回顾提交历史并不友好的合并记录,还是采用 --ff-only 方式
rebase 操作会丢弃当前分支已提交的 commit,故不要在已经 push 到远程,和其他人正在协作开发的分支上执行 rebase 操作
与远程仓库同步时,使用 pull 命令默认进行了 git fetch + git merge --no-ff 两个操作,可以通过加上 --rebase 命令将 fetch 后的 merge 操作改为 rebase 操作,或者仅仅 'git fetch remoteName',然后才思考采取哪种整合策略 git merge(or rebase) origin/master
开发与 commit 时注意自己此时在哪个分支上
当有修改未 commit 时,不能进行 rebase 操作,此时可以考虑先用 git stash 命令暂存
⑦ git rebase 解决完冲突执行什么命令
结果是from_branch的代码更新到to_branch, 同时to_branch的commit log加到from_branch的最前方。例子:1. git rebase remotes/main/master MYBRANCH从远程主fork的master分支到本地分支MYBRANCH进行rebase。
⑧ git rebase i怎么返回
想象一下你正在开发一个激进的新功能。这将是很灿烂的但它需要一段时间。您这几天也许是几个星期一直在做这个。
你的功能分支已经超前master有6个提交了。你是一个优秀的开发人员并做了有意义的语义提交。但有一件事情:你开始慢慢意识到,这个疯狂的东西仍需要更多的时间才能真的做好准备被合并回主分支。
m1-m2-m3-m4 (master) \ f1-f2-f3-f4-f5-f6(feature)
你也知道的是,一些地方实际上是交叉不大的新功能。它们可以更早地合并到主分支。不幸的是,你想将部分合并到主分支的内容存在于你六个提交中的某个地方。更糟糕的是,它也包含了依赖于你的功能分支的之前的提交。有人可能会说,你应该在第一处地方做两次提交,但没有人是完美的。
m1-m2-m3-m4 (master) \ f1-f2-f3-f4-f5-f6(feature) ^ | mixed commit
在你准备提交的时间,你没有预见到,你可能要逐步把该功能合并入主分支。哎呀!你不会想到这件事会有这么久。
你需要的是一种方法可以回溯历史,把它并分成两次提交,这样就可以把代码都安全地分离出来,并可以移植到master分支。
用图说话,就是我们需要这样。
m1-m2-m3-m4 (master) \ f1-f2-f3a-f3b-f4-f5-f6(feature)
在将工作分成两个提交后,我们就可以cherry-pick出前面的部分到主分支了。
原来Git自带了一个功能强大的命令git rebase -i ,它可以让我们这样做。它可以让我们改变历史。改变历史可能会产生问题,作为一个经验,应尽快避免历史与他人共享。不过在我们的例子中,我们只是改变我们的本地功能分支的历史。没有人会受到伤害。就这么做了!
好吧,让我们来仔细看看f3提交究竟修改了什么。原来我们共修改了两个文件:userService.js和wishlistService.js。比方说,userService.js的更改可以直接合入主分支而wishlistService.js不能。因为wishlistService.js甚至不存在在主分支里面。它是f1提交中引入的。
专家提示:即使是在一个文件中更改,git也可以搞定。但这篇博客中我们先简化情况。
我们已经建立了一个公众演示仓库,我们将使用这个来练习。为了便于跟踪,每一个提交信息的前缀是在上面的图表中使用的假的SHA。以下是git在分开提交f3时的分支图。
现在,我们要做的第一件事就是使用git的checkout功能checkout出我们的功能分支。用git rebase -i master开始做rebase。
现在接下来git会用所配置的编辑器打开(默认为Vim)一个临时文件。
该文件为您提供一些rebase选择,它带有一个提示(蓝色文字)。对于每一个提交,我们可以选择的动作有pick、rwork、edit、squash、fixup和exec。每一个动作也可以通过它的缩写形式p、r、e、s、f和e引用。描述每一个选项超出了本文范畴,所以让我们专注于我们的具体任务。
我们要为f3提交选择edit选项,因此我们把内容改变成这样。
现在我们保存文件(在Vim中是按下后输入:wq,最后是按下回车)。接下来我们注意到git在编辑选项中选择的提交处停止了rebase。
这意味这git开始将f1、f2、f3生效仿佛它就是常规的rebase,但是在f3生效之后停止。事实上,我们可以看一眼停止的地方的日志就可以证明这一点。
要将f3分成两个提交,我们所要做的是重置git的指针到先前的提交(f2)而保持工作目录和现在一样。这就是git reset在混合模式在做的。由于混合模式是git reset的默认模式,我们可以直接用git reset head~1。就这么做并在运行后用git status看下发生了什么。
git status告诉我们userService.js和wishlistService.js被修改了。如果我们运行 git diff 我们就可以看见在f3里面确切地做了哪些更改。
如果我们看一眼日志我们会发现f3已经消失了。
现在我们有了准备提交的先前的f3提交,而原先的f3提交已经消失了。记住虽然我们仍旧在rebase的中间过程。我们的f4、f5、f6提交还没有缺失,它们会在接下来回来。
让我们创建两个新的提交:首先让我们为可以提交到主分支的userService.js创建一个提交。运行git add userService.js 接着运行 git commit -m "f3a: add updateUser method"。
太棒了!让我们为wishlistService.js的改变创建另外一个提交。运行git add wishlistService.js,接着运行git commit -m "f3b: add addItems method".
让我们在看一眼日志。
这就是我们想要的,除了f4、f5、f6仍旧缺失。这是因为我们仍在rebase交互的中间,我们需要告诉git继续rebase。用下面的命令继续:git rebase --continue。
让我们再次检查一下日志。
就是这样。我们现在已经得到我们想要的历史了。先前的f3提交现在已经被分割成两个提交f3a和f3b。剩下的最后一件事是cherry-pick出f3a提交到主分支上。
为了完成最后一步,我们首先切换到主分支。我们用git checkout master。现在我们就可以用cherry-pick命令来拾取f3a commit了。本例中我们可以用它的SHA值bd47ee1来引用它。
现在f3a这个提交就在主分支的最上面了。这就是我们需要的!
这篇文章的长度看起来需要花费很大的功夫,但实际上对于一个git高级用户而言这只是一会会。
⑨ git rebase 之后可以回退吗
git rebase 不会取回代码 要用git fetch先取回, git rebase 是合并代码。
(1)首先用git fetch返回服务器上的代码
(2)首先用git rebase origin/master 合并
(3)如果发生冲突了会提示, 然后可以使用git diff查看冲突, 在手工改掉冲突, 在用git add ‘文件名’ 添加修改后文件,最后用git rebase --continue继续没完成的合并
(4)最后就可以用git push 更新到服务器上去。
转自: http://blog.chinaunix.net/uid-26952464-id-3352144.html
Git Community Book 中文版书上,摘录如下:
一、基本
git rebase用于把一个分支的修改合并到当前分支。
假设你现在基于远程分支"origin",创建一个叫"mywork"的分支。
$ git checkout -b mywork origin
假设远程分支"origin"已经有了2个提交,如图
现在我们在这个分支做一些修改,然后生成两个提交(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)
二、解决冲突
在rebase的过程中,也许会出现冲突(conflict).
在这种情况,Git会停止rebase并会让你去解决 冲突;在解决完冲突后,用"git-add"命令去更新这些内容的索引(index),
然后,你无需执行 git-commit,只要执行:
$ git rebase --continue
这样git会继续应用(apply)余下的补丁。
在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。
$ git rebase --abort
三、git rebase和git
merge的区别
现在我们可以看一下用合并(merge)和用rebase所产生的历史的区别:
当我们使用Git log来参看commit时,其commit的顺序也有所不同。
假设C3提交于9:00AM,C5提交于10:00AM,C4提交于11:00AM,C6提交于12:00AM,
对于使用git merge来合并所看到的commit的顺序(从新到旧)是:C7
,C6,C4,C5,C3,C2,C1
对于使用git rebase来合并所看到的commit的顺序(从新到旧)是:C7
,C6‘,C5',C4,C3,C2,C1
因为C6'提交只是C6提交的克隆,C5'提交只是C5提交的克隆,
从用户的角度看使用git rebase来合并后所看到的commit的顺序(从新到旧)是:C7
,C6,C5,C4,C3,C2,C1
参考资料:http://www.cnblogs.com/kym/archive/2010/08/12/1797937.html
git
rebase小计(转)
git rebase,顾名思义,就是重新定义(re)起点(base)的作用,即重新定义分支的版本库状态。要搞清楚这个东西,要先看看版本库状态切换的两种情况:
我们知道,在某个分支上,我们可以通过git reset,实现将当前分支切换到本分支以前的任何一个版本状态,即所谓的“回溯”。即实现了本分支的“后悔药”。也即版本控制系统的初衷。
还有另一种情况,当我们的项目有多个分支的时
候。我们除了在本地开发的时候可能会“回溯”外,也常常会将和自己并行开发的别人的分支修改添加到自
己本地来。这种情况下很常见。作为项目管理员,肯定会不断的合并各个子项目的补丁,并将最新版本推送到公共版本库,而作为开发人员之一,提交自己的补丁之
后,往往需要将自己的工作更新到最新的版本库,也就是说把别的分支的工作包含进来。
举个例子来说吧!假设我们的项目初期只有一个master分支,然后分支上作过两次提交。这个时候系统只有一个master分支,他的分支历史如下:
master0(初始化后的版本)
||
v
master1(第一次提交后的版本)
||
v
master2(第二次提交后的版本)
这个时候,我们可以通过git reset将master分支(工作目录、工作缓存或者是版本库)切换到master1或者master0版本,这就是前面所说的第一种情况。
假设我们这里把master分支通过git reset回溯到了master1状态。那么这个时候系统仍然只有一个master分支,分支的历史如下:
master0(初始化后的版本)
||
v
master1(第一次提交后的版本)
然后,我们在这里以master1为起点,创建了另一个分支test。那么对于test分支来说,他的第一个版本test0就和master1是同一个版本,此时项目的分支历史如下:
master0(初始化后的版本)
||
v
master1(第一次提交后的版本)===test0(test分支,初始化自master分支master1状态)
这个时候,我们分别对master分支、test分支作两次提交,此时版本库应该成了这个样子:
master0(初始化后的版本)
||
v
master1===test0==>test1===>test2
||
v
master2===>master3
这个时候,通过第一种git
reset的方式,可以将master分支的当前状态(master3)回溯到master分支的master0、master1、master2状态。
也可已将test分支当前状态(test2)回溯到test分支的test0、test1状态,以及test分支的父分支master的master0、
master1状态。
那么。如果我要让test分支从test0到test2之间所有的改变都添加到master分支来,使得master分支包含test分支的所有修改。这个时候就要用到git rebase了。
首先,我们切换到master分支,然后运行下面的命令,即可实现我们的要求:
git rebase test
这个时候,git做了些什么呢?
先将test分支的代码checkout出来,作为工作目录
然后将master分支从test分支创建起的所有改变的补丁,依次打上。如果打补丁的过程没问题,rebase就搞定了
如果打补丁的时候出现了问题,就会提示你处理冲突。处理好了,可以运行git rebase –continue继续直到完成
如果你不想处理,你还是有两个选择,一个是放弃rebase过程(运行git rebase –abort),另一个是直接用test分支的取代当前分支的(git rebase –skip)。
⑩ Git push,merge,pull,fetch,rebase各自在什么场景下使用
基本上顺序是这样的:
你修改好了代码,先要提交
git commit -am “commit message"
然后有两种方法来把你的代码和远程仓库中的代码合并
a. git pull这样就直接把你本地仓库中的代码进行更新但问题是可能会有冲突(conflicts),个人不推荐
b. 先git fetch origin(把远程仓库中origin最新代码取回),再git merge origin/master(把本地代码和已取得的远程仓库最新代码合并),如果你的改动和远程仓库中最新代码有冲突,会提示,再去一个一个解决冲突,最后再从1开始
如果没有冲突,git push origin master,把你的改动推送到远程仓库中
至于rebase很容易和merge混淆,因为就结果而言,两条命令是类似的,具体请看
http://git-scm.com/book/zh/ch3-6.html