我已经从GitHub的存储库中分叉了一个分支,并提交了一些具体的东西给我。现在我发现原来的存储库有一个很好的功能,这是在HEAD。
我想合并它只是没有以前的提交。我该怎么办?我知道如何合并所有的提交:
git branch -b a-good-feature
git pull repository master
git checkout master
git merge a-good-feature
git commit -a
git push
我已经从GitHub的存储库中分叉了一个分支,并提交了一些具体的东西给我。现在我发现原来的存储库有一个很好的功能,这是在HEAD。
我想合并它只是没有以前的提交。我该怎么办?我知道如何合并所有的提交:
git branch -b a-good-feature
git pull repository master
git checkout master
git merge a-good-feature
git commit -a
git push
当前回答
让我们举个例子来理解:
我有一个分支,比如master,指向X <commit-id>,还有一个新分支指向Y <sha1>。
哪里Y <commit-id> = <主>分支提交-很少提交
现在,对于Y分支,我必须关闭主分支和新分支之间的提交。下面是我们可以遵循的程序:
步骤1:
git checkout -b local origin/new
其中local是分支名称。任何名字都可以给出。
步骤2:
git merge origin/master --no-ff --stat -v --log=300
合并从主分支到新分支的提交,并创建一个日志消息的合并提交,其中包含来自最多<n>个正在合并的实际提交的一行描述。
有关Git合并的更多信息和参数,请参考:
git merge --help
另外,如果你需要合并一个特定的提交,那么你可以使用:
git cherry-pick <commit-id>
其他回答
在我的用例中,我们对CI CD有类似的需求。 我们使用git流来开发和master分支。 开发人员可以自由地将他们的更改直接合并到开发中,或者通过来自功能分支的拉请求进行合并。但是为了master,我们通过Jenkins以自动的方式合并来自开发分支的稳定提交。
在这种情况下,做樱桃选择不是一个好的选择。然而,我们从commit-id创建一个本地分支,然后将该本地分支合并到master并执行mvn清洁验证(我们使用maven)。如果成功,则使用maven发布插件,使用localCheckout=true选项和pushChanges=false将产品版本工件发布到nexus。最后,当一切都成功时,再将更改和标签推到原点。
示例代码片段:
假设您是在主,如果手动完成。然而在jenkins上,当你签出repo时,你将在默认分支上(如果配置为master)。
git pull // Just to pull any changes.
git branch local-<commitd-id> <commit-id> // Create a branch from the given commit-id
git merge local-<commit-id> // Merge that local branch to master.
mvn clean verify // Verify if the code is build able
mvn <any args> release:clean release:prepare release:perform // Release artifacts
git push origin/master // Push the local changes performed above to origin.
git push origin <tag> // Push the tag to origin
这将给你一个无所畏惧的合并或冲突地狱完全控制。
如果有更好的选择,请随时提出建议。
Git -pick应该是你的答案。
应用现有提交引入的更改。
不要忘记阅读bdonlan在这篇文章中关于择优选择后果的回答: “从一个分支中提取所有提交,将指定的提交推到另一个分支”,其中:
A-----B------C
\
\
D
就变成:
A-----B------C
\
\
D-----C'
这个提交的问题是git认为提交包含了它们之前的所有历史
其中C'有不同的SHA-1 ID。 同样地,从一个分支向另一个分支选择提交基本上涉及生成一个补丁,然后应用它,因此也会丢失历史记录。
这种提交id的改变破坏了git在其他事情之间的合并功能(尽管如果谨慎使用,有一些启发式方法会掩盖这一点)。 更重要的是,它忽略了函数依赖关系——如果C语言真的使用了B语言中定义的函数,你永远不会知道。
让我们举个例子来理解:
我有一个分支,比如master,指向X <commit-id>,还有一个新分支指向Y <sha1>。
哪里Y <commit-id> = <主>分支提交-很少提交
现在,对于Y分支,我必须关闭主分支和新分支之间的提交。下面是我们可以遵循的程序:
步骤1:
git checkout -b local origin/new
其中local是分支名称。任何名字都可以给出。
步骤2:
git merge origin/master --no-ff --stat -v --log=300
合并从主分支到新分支的提交,并创建一个日志消息的合并提交,其中包含来自最多<n>个正在合并的实际提交的一行描述。
有关Git合并的更多信息和参数,请参考:
git merge --help
另外,如果你需要合并一个特定的提交,那么你可以使用:
git cherry-pick <commit-id>
前面的答案描述了如何将特定提交的更改应用到当前分支。如果这就是你所说的“如何合并”,那么就按照他们的建议进行选择。
但是如果你真的想要合并,也就是说,你想要一个有两个父节点的新提交——当前分支上现有的提交,以及你想要应用更改的提交——那么选择是不能实现的。
拥有真实的合并历史可能是可取的,例如,如果您的构建过程利用git祖先来根据最新标记自动设置版本字符串(使用git describe)。
而不是选择,你可以做一个实际的git合并-不提交,然后手动调整索引,删除任何你不想要的变化。
假设你在分支A上,你想合并分支B顶端的提交:
git checkout A
git merge --no-commit B
现在,您已经准备好创建一个带有两个父类的提交,即a和B的当前提示提交。然而,您可能应用了比您想要的更多的更改,包括来自B分支早期提交的更改。您需要撤消这些不需要的更改,然后提交。
(可能有一种简单的方法可以将工作目录的状态和索引设置回合并之前的状态,这样您就可以在一个干净的石板上选择您想要的提交。但我不知道怎样才能重新开始。git checkout HEAD和git reset HEAD都将删除合并状态,违背了此方法的目的。)
因此,手动撤消不需要的更改。例如,你可以
git revert --no-commit 012ea56
对于每个不想要的提交012ea56。
当你完成调整时,创建你的commit:
git commit -m "Merge in commit 823749a from B which tweaked the timeout code"
现在您只有想要的更改,并且祖先树显示您从技术上合并了B。
如果你是新手,尝试GitHub桌面版本,当你选择选择选项时,GitHub会要求你选择你想要提交的分支。
1)
2)