不管是merge,还是rebase都是将一个分支的修改合并到另一个分支,但是方式方法有所不同,下面我们具体来看下每种情况。
merge就是合并代码,这种方式合并代码后,合并的结果会生成一个新的commit(效果同手动修改后的提交),而merge又有两种方式分别是fast-forward和,非fast-forward,分别来看下这两种方式。
当合并代码的时候,如果是没有冲突(更准确的表述应该是文件不需要合并时),git就会默认采用这种方式,接下来看下具体操作。
$ git checkout -b dev100
Switched to a new branch 'dev100'
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git push origin dev100:dev100
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.3]
remote: Create a pull request for 'dev100' on Gitee by visiting:
remote: https://gitee.com/dongsir2020/test-cherry-pick/pull/new/dongsir2020:dev100...dongsir2020:master
To https://gitee.com/dongsir2020/test-cherry-pick.git
* [new branch] dev100 -> dev100
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git branch --set-upstream-to=origin/dev100
Branch 'dev100' set up to track remote branch 'dev100' from 'origin'.
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git branch -vv
dev 1d2f221 dev first commit
dev10 09ea18b [origin/dev10] dev second add content
* dev100 09ea18b [origin/dev100] dev second add content
master 09ea18b [origin/master] dev second add content
命令git branch --set-upstream-to=origin/dev100是用来关联本地的dev100到远程的dev100分支。
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ touch dev100.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git status
On branch dev100
Your branch is up to date with 'origin/dev100'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
dev100.txt
nothing added to commit but untracked files present (use "git add" to track)
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git add dev100.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git commit -am'add dev100.txt'
[dev100 cebe7f0] add dev100.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dev100.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ vim dev100.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git commit -am'add some content in dev100.txt'
warning: LF will be replaced by CRLF in dev100.txt.
The file will have its original line endings in your working directory
[dev100 8adeee0] add some content in dev100.txt
1 file changed, 1 insertion(+)
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git status
On branch dev100
Your branch is ahead of 'origin/dev100' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev100)
$ git push origin dev100:dev100
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 459 bytes | 459.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.3]
To https://gitee.com/dongsir2020/test-cherry-pick.git
09ea18b..8adeee0 dev100 -> dev100
此时相比master新增的提交如下:
$ git log -n2 --pretty=oneline
8adeee00933d01888f128ced8193e728f99faf1f (HEAD -> dev100, origin/dev100) add some content in dev100.txt
cebe7f0df20707a6a55419a310671c5fb3fc1b95 add dev100.txt
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (master)
$ git branch
dev
dev10
dev100
* master
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (master)
$ git merge dev100
Updating 09ea18b..8adeee0
Fast-forward
dev100.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 dev100.txt
通过输出Fast-forward就可以知道使用了fast forward方式,此时查看master的历史记录:
$ git log --pretty=oneline -n4 --graph
* 8adeee00933d01888f128ced8193e728f99faf1f (HEAD -> master, origin/dev100, dev100) add some content in dev100.txt
* cebe7f0df20707a6a55419a310671c5fb3fc1b95 add dev100.txt
* 09ea18b4302ede38ddc42e7051e14593c1862e9a (origin/master, origin/dev10, origin/HEAD, dev10) dev second add content
* 8497aa644b7c63d4c1d59b5cd9a1bf9dc19eb136 dev first commit
提交记录是有的,但是并不能体现出到底是从哪个分支合并过来的代码其实仅仅是改变了指针的指向,这不利于我们维护代码,因为有时这些信息对我们还是很有用的,此时就可以考虑使用非fast forward的方式,我们继续往下看。
想要使用none fast-forward方式也比较简单,只需要在merge时增加参数–no-ff即可,如下实验过程。
$ git branch
dev
dev10
dev100
* master
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (master)
$ git checkout -b dev101
Switched to a new branch 'dev101'
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git push origin dev101:dev101
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.3]
remote: Create a pull request for 'dev101' on Gitee by visiting:
remote: https://gitee.com/dongsir2020/test-cherry-pick/pull/new/dongsir2020:dev101...dongsir2020:master
To https://gitee.com/dongsir2020/test-cherry-pick.git
* [new branch] dev101 -> dev101
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git branch --set-upstream-to=origin/dev101
Branch 'dev101' set up to track remote branch 'dev101' from 'origin'.
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git branch -vv
dev 1d2f221 dev first commit
dev10 09ea18b [origin/dev10] dev second add content
dev100 8adeee0 [origin/dev100] add some content in dev100.txt
* dev101 8adeee0 [origin/dev101] add some content in dev100.txt
master 8adeee0 [origin/master] add some content in dev100.txt
$ touch 101.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git add *
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git commit -am'add 101.txt'
[dev101 065f581] add 101.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 101.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ vim 101.txt
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git commit -am'add some content in 101.txt'
warning: LF will be replaced by CRLF in 101.txt.
The file will have its original line endings in your working directory
[dev101 0e2c8a0] add some content in 101.txt
1 file changed, 1 insertion(+)
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev101)
$ git push origin dev101:dev101
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (5/5), 488 bytes | 488.00 KiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Powered by GITEE.COM [GNK-6.3]
To https://gitee.com/dongsir2020/test-cherry-pick.git
8adeee0..0e2c8a0 dev101 -> dev101
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (master)
$ git merge dev101 --no-ff
Merge made by the 'recursive' strategy.
101.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 101.txt
注意git merge dev101 --no-ff时会弹出一个窗口让我们录入生成的新提交的注释信息,我这里录入的是这是--no-ff方式合并产生的新提交的comment,此时log如下:
$ git log -n4 --pretty=oneline --graph
* 291d49a04f24dd2f266d74d7f1f63406c2632c1e (HEAD -> master) 这是--no-ff方式合并产生的新提交的comment
|\
| * 0e2c8a01e24715b45386b10f0a75b6b4d6215c07 (origin/dev101, dev101) add some content in 101.txt
| * 065f5815cf2505c1ff0feb4f0931056211f42ba2 add 101.txt
|/
* 8adeee00933d01888f128ced8193e728f99faf1f (origin/master, origin/dev100, origin/HEAD, dev100) add some content in dev100.txt
可以看到保留了合并分支的信息,并生成了一个提交的日志291d49a04f24dd2f266d74d7f1f63406c2632c1e (HEAD -> master) 这是--no-ff方式合并产生的新提交的comment。个人觉得这种方式比较好,很清晰。
git rebase有时怎样呢?我们继续来一起看下。
rebase翻译过来就是变基,那么这个基是什么呢,比如当前master分支的提交状态如下:

然后我们使用命令git checkout -b feature,创建了feature分支,然后有执行了提交B1,B2(产生提交并不必须,只是为了好描述),此时如下图:

那么此时feature分支的基就是A3,知道了什么是基,变基就清晰了,就是改变这个基,而改变这个基的命令就是git rebase。这种操作个人认为最大的坏处就是破坏了实际的提交记录,改变了代码提交实际的时间线,我们通过一个实际的例子来看下。
首先从master创建test,dev两个分支,然后分别在两个分支上执行2次提交(注意提交内容在合并时不要产生冲突,这里不考虑rebase有冲突的情况),变为下图:

准备完毕后,查询test,dev两个分支的提交记录如下:
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev)
$ git log --pretty=oneline -n2
90f470ed681d6ecdc43cbddbea6b846714cc7a7f (HEAD -> dev) dev2
4a386b2c4d4974d0b9aaa650540a4deb589a25f1 dev1
----------------华丽的分割线--------------
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (test)
$ git log -n2 --pretty=oneline
620f696b01e25185185eddc8661c533f59aabcac (HEAD -> test) test2
16c55db40582ac77d8f76e18a44583bcf3369499 test1
接下来我们合并test分支到dev分支,只需要让dev变基到test即可,执行如下操作:
$ git checkout dev
Switched to branch 'dev'
JHP+Administrator@jhp MINGW64 /d/test/test-cherry-pick (dev)
$ git rebase test
Successfully rebased and updated refs/heads/dev.
此时查看dev的提交日志:
$ git log -n4 --pretty=oneline
b7b9b230af21686b822ebe80edb6ed71d97c488e (HEAD -> dev) dev2
cfdc1108b0d42a1b516a1fed8310cc438e1d866e dev1
620f696b01e25185185eddc8661c533f59aabcac (test) test2
16c55db40582ac77d8f76e18a44583bcf3369499 test1
可以看到test的提交日志插入到了dev自身提交日志之前,如果魔法一般,这就是变基的结果,此时结构变为下图:

merge fast-forward方式是在合并代码时,不需要真正的合并文件就能完成合并时采用的方式,通过简单的移动指针达到效果,合并效率高,但是因为没有真正的合并,所以不会产生合并的记录,即不会有分叉产生,一旦需要合并文件(自然包括有冲突的情况)就会使用none fast forward方式,也可以通过参数–no-ff禁用fast forward,这样保证不管什么情况都是明显的合并记录生成。
rebase因为变基,所以会改变代码提交的时间线,修改程序的实际的提交记录,让代码管理陷入混乱,虽然解决了合并产生的复杂分叉的问题,但是引入的问题也更多,出现问题时,无法正常的通过代码提交查找问题,无法正常的回滚代码等,所以建议非必要就不要使用rebase方式合并代码,而是使用merge配合–no-ff参数的方式,这样能够在保证保留了足够多代码合并信息的同时,也不会改变已有的代码提交历史,唯一的不足的可能就是多了一次因合并而产生的commit而已,不过这又有什么问题呢!。
参考网址:
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g
关于如何使用git设置类似Dropbox的服务,您有什么建议吗?您认为git是解决此问题的合适工具吗?我在考虑使用git+rush解决方案,你觉得怎么样? 最佳答案 检查这个开源项目:https://github.com/hbons/SparkleShare来自项目的自述文件:Howdoesitwork?SparkleSharecreatesaspecialfolderonyourcomputer.Youcanaddremotelyhostedfolders(or"projects")tothisfolder.Theseprojec
我编写了一个非常简单的“部署”脚本,作为我的裸git存储库中的post-updateHook运行。变量如下livedomain=~/mydomain.comstagingdomain=~/stage.mydomain.comgitrepolocation=~/git.mydomain.com/thisrepo.git(bare)core=~/git.mydomain.com/thisrepo.gitcore==addedremoteintoeachlive&stagegitslive和stage都初始化了gitrepos(非裸),我已经将我的裸仓库作为远程添加到它们中的每一个(名为co
我正在安装gitlabhq,并且在Gemfile中有对某些资源的“git://...”的引用。但是,我在公司防火墙后面,所以我必须使用http://。我可以手动编辑Gemfile,但我想知道是否有另一种方法告诉bundler使用http://作为git存储库? 最佳答案 您可以通过运行gitconfig--globalurl."https://".insteadOfgit://或通过将以下内容添加到~/.gitconfig:[url"https://"]insteadOf=git://
在Ruby(或Rails)中,我们可以做到new_params=params.merge({:order=>'asc'})现在new_params是一个带有添加键:order的散列。但是是否有一行可以返回带有已删除key的散列?线路new_params=params.delete(:order)不会工作,因为delete方法返回值,仅此而已。我们必须分3步完成吗?tmp_params=paramstmp_params.delete(:order)returntmp_params有没有更好的方法?因为我想做一个new_params=(params[:order].blank?||para
Activeadmingem已添加到我的rails项目中,但每次我尝试安装railsgactive_admin:install时,我都会收到类似的错误git://github.com/activeadmin/activeadmin.git(atmaster)isnotyetcheckedout.Runbundleinstallfirst.我肯定在运行“railsgactive_admin:install”之前运行了bundle。运行“bundleshow”后,我看到我已将“*activeadmin(1.0.0.pre3f916d6)”添加到我的项目中,但不断收到此错误消息。我的gem文
编辑:经过进一步测试,问题似乎是站点特定的,理论上应该可以正常工作。本应位于多行的Textarea值正在一行中全部提交。textarea_values="value1\nvalue2"form=page.form_with(:id=>'form_id_here')form['my_textarea']=textarea_valuessubmit=form.button_with(:value=>'Submit')form.click_button(submit)提交的值是value1\nvalue2而不是预期的多行。有没有我可以尝试的另一种添加表单值的方法?
我在bitbucket上创建了一个私有(private)git存储库并提交了代码。现在我想导出所有(提交、代码、历史记录)并将其导入github上的gitrepo。有没有办法做到这一点?谢谢 最佳答案 在本地检查所有内容到您的计算机和gitpull。创建一个github存储库将此存储库添加为您的第二个远程(“使用gitremote添加githubURL”)推送到第二个Remote 关于ruby-git:从bitbucket导出并导入github(带提交),我们在StackOverflow
亲测可用。Anerroroccurredwhileresolvingpackages:Projecthasinvaliddependencies: com.unity.xxx:No'git'executablewasfound.PleaseinstallGitonyour systemthenrestartUnityandUnityHub在我们使用PackageManager时,Unity允许我们使用Git上的package(点击加号,选择addpackagefromgitURL,或者是直接在Asset/Packages/manifest.json中添加包名)。但是这种操作需要我们事先装好g