我想重新定义一个特定的提交,而不是另一个分支的HEAD:
A --- B --- C master
\
\-- D topic
Run Code Online (Sandbox Code Playgroud)
至
A --- B --- C master
\
\-- D topic
Run Code Online (Sandbox Code Playgroud)
代替
A --- B --- C master
\
\-- D topic
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
有极少数的Q&A的上的git grafts对replace.搜索[git] + grafts + replace只发现了两个与5. what-are-git-info-grafts-for和git-what-a-a-graftcommit-or-a-graft-id相关的两个.git.wiki.kernel.org:GraftPoint上还有一个注释
被移植现在完全取代由replace和filter-branch,或者他们仍然需要一些特殊的情况(和向后兼容)?
一般来说,它们如何不同(例如哪些在回购之间运输),它们通常是如何相同的?我已经看到Linus似乎并不关心目前在关于提交代数的讨论(最大父母回到任何根种类)的问题"移植已经不可靠了."
编辑:找到更多信息.
搜索www.kernel.org/pub/software/scm/git/docs graft仅找到3个结果:
稍微宽泛的搜索发现RelNotes/1.6.5.txt包含:
- refs/replace/hierarchy被设计为可用作"移植"机制的替代,其附加优势是它可以跨存储库传输.
不幸的是,gitrepository-layout(5)还没有更新refs/replace/repository布局信息(和注释),也没有任何信息/移植的弃用说明.
这更接近支持我的想法,但我欢迎任何确认或澄清.
我收到了一些源代码并决定使用git,因为我的同事使用了mkdir $VERSION等方法.虽然代码的过去目前似乎并不重要,但我仍然希望将其置于git控制之下以更好地理解开发过程.所以:
将这些过去的版本放入我现有的git仓库的简便方法是什么?目前没有远程仓库,所以我不介意重写历史记录,但考虑到远程存储库的解决方案当然是首选,除非它更复杂.基于目录或基于档案文件的历史记录,不需要任何更多交互的脚本的加分点.
我曾经git-svn创建过SVN存储库的git镜像.SVN内部的结构有点不合标准,因此git创建了一个与分支没有共同提交的master分支.
A---B---C topic
D---E---F---G master
Run Code Online (Sandbox Code Playgroud)
我知道提交A是基于提交的E,我非常肯定我已经解决了导致git无法识别该事实(使用filter-branch)的问题.我想要做的是重新连接topic到master分支,设置E为以下的父代A:
A---B---C topic
/
D---E---F---G master
Run Code Online (Sandbox Code Playgroud)
git-rebase似乎对我没有用,因为提交的差异A列出了已经存在的大量文件的创建master,导致了大量的冲突.
从我对git的理解只是设置E为父母A应该足以解决所有问题.
这可能吗?如果是,我该怎么办?
我有三个回购 - 名称已更改为清晰:
SharedStuff,ProjectA和ProjectB
这两个项目都使用git-subtree来维护本地副本SharedStuff.他们都进行了本地更改,我正在尝试集中合并,测试,然后再次合并到每个.
我在ProjectA回购中运行了这个:
git subtree split --prefix=SharedStuff -b SharedStuff_from_ProjectA --rejoin
...然后将其推送到SharedStuff回购,解决了一些简单的冲突,将其合并.
现在我在ProjectB repo上运行它:
git subtree split --prefix=platform/SharedStuff -b SharedStuff_from_Project_B --rejoin
......然后又把它推到了SharedStuff一个新的分支中.当我尝试合并这些更改时,会出现问题.
在当前的情况下,我切换到SharedStuff_from_Project_B分支,然后git merge master- 但我立即将所有更改的文件列为添加/添加冲突.当我运行时git mergetool,每个人都有这样的错误:
Merging:
somefile.xyz
Normal merge conflict for 'somefile.xyz':
{local}: created file
{remote}: created file
fatal: invalid path './somefile.xyz_BASE_20704.cs'
Run Code Online (Sandbox Code Playgroud)
(当然,如果我尝试相反的方式 - 合并SharedStuff_from_Project_B到master- 我得到相同类型的冲突,只是逆转.仍然添加/添加).
我的猜测是ProjectB的历史可能有问题,导致添加/添加的外观.不过我不确定如何进一步诊断 - 我该怎么办?
编辑:之前有一个子树"rejoin"提交ProjectB,但SharedStuff …
假设我的Git存储库最初有两个分支:Foo和Bar.
... ? Foo ... ? Bar
我创建了第三个分支,FooBar,其中我提交了另外两个分支的合并.
... ? Foo ???
FooBar
... ? Bar ???
FooBar现在领先于Foo和Bar.接下来,我做了一些工作,仅在Foo上做了几次.
... ?? A ?????? B ?? C ?? D ?? Foo
FooBar
... ? Bar ???
问题是:由于分支FooBar的第一个父亲不再是Foo,我可以在分支FooBar中重新合并提交以再次将Foo和Bar作为其两个父母吗?换句话说,我可以将Foo中的开发项目与未更改的Bar一起合并到之前合并的FooBar中吗?
... ?? A ?? B ?? C ?? D ?? Foo ???
FooBar
... ? Bar ????????????????????????
假设我有以下历史记录,其中顶行是主分支,较低的一个是在一个点与主服务器合并的功能分支,D只是恢复C(这意味着工作目录在B和中是相同的D).
A---B---C---D master
\ \
E---F---G feature
Run Code Online (Sandbox Code Playgroud)
我想在合并之前添加C并恢复D历史记录F,如下所示:
A---B---C---D master
\ \
E-----------F'--G' feature
Run Code Online (Sandbox Code Playgroud)
我不想改变E(这实际上是一系列提交).
git rebase --onto D B(如此处所示)导致合并冲突(有或没有--preserve-merges).
有没有办法实现我想要的?
我正在尝试将Subversion存储库转换为Git。我面临的问题是如何保留完整的完整历史记录。SVN存储库具有相当复杂的历史记录,然后git-svn起作用,它仅从特定版本开始,而忽略了所有较早的历史记录。
更多详细信息:我想导入一个现在按std-layout定位的项目http://svn.../projects/myProject/trunk。但是,trunk不会像现在那样在SVN中创建。它最初是作为一些自定义路径创建的,例如/my_project,然后在SVN中myProject/trunk重命名为,然后又进行了多次移动和重命名,最终以标准布局结束。
因此,如果我只是按原样导入指向我所需的SVN项目文件夹的存储库,则git-svn结果将从引入标准布局的修订版本开始历史记录,而忽略了projects/myProject/trunk将存储库更早地移入存储库的事实。
从技术上讲,如果将SVN文件夹的历史记录从同一存储库的其他位置(在主干外部)移动/复制到主干中,则需要导入它。
是否有人有任何想法如何从此类存储库中恢复历史记录?也许以某种方式使用多个导入,然后使用gitgrafs或其他某种魔术?有什么简单的方法吗?
有一个git相当于hg rebase -s source -d newparent?
也就是说,"修剪"一个分支source并"嫁接"它newparent.或重新设置父级source的newparent(合并在适当情况下).
或者如何从这个例子:
A - B - C
\
D - E
\
F
Run Code Online (Sandbox Code Playgroud)
对此:
A - B - C
\
D'- E'
\
F'
Run Code Online (Sandbox Code Playgroud)
在这种情况下,source是D,newparent是B.做hg rebase -s D -d B产生所需的结果.有一个git等价物吗?
我试过了,git rebase --onto B D但除了移动分支标签外,它显然没有做任何事情.
编辑澄清:目标不是在树中重新提交与上面完全相同的提交.以上就是一个例子.我的目标是让我在任何其他提交之上重新提交一个提交,只要没有像尝试重新提交合并提交或类似的那样奇怪的情况.我创建了几个重新创建上面树的脚本,一个用于hg:
#!/bin/sh
set -e
rm -rf .hg
hg init
cat > .hg/hgrc <<'EOF'
[ui] …Run Code Online (Sandbox Code Playgroud) 我已经“继承”了一个肮脏的git存储库,其中包含约5k个有效提交和约5万个垃圾邮件提交(这是以前是世界可写的wiki的编辑历史记录)。我们正在迁移格式,因此这是重写历史记录的好时机。我不想完全放弃历史记录,但是无论从提交量还是原始内容量来看,垃圾邮件都是压倒性的。回滚到最后一次良好提交的旧审核技术留下了很多垃圾。
我可以发现大约80%的错误提交没有太多使用麻烦git log -S和一些正则表达式的工作。大多数垃圾邮件内容非常明显。问题是我不确定要删除的大量提交会如何处理。
请注意,我非常熟悉git并git rebase每小时使用一次(除非git revise承担了很多负载,否则每分钟都会这样做),而且我知道如何手动完成此操作,但是我需要一个自动化的解决方案。通常情况下,我会转向git filter-branch,但是我不确定要使用哪种工具来检查当前差异。
我曾考虑过编写一个脚本来操纵一个rebase脚本,但是我认为这会给我带来误报的麻烦。我可能可以捕获和删除原始的删除和回滚,但是当我错过该方程式的一侧时会发生什么?我希望可能的匹配中的REST成功,如果其中之一没有完全重新设置基准就不会失败。
注意我不想基于我的匹配来操纵文件的内容或添加/删除文件,我想检查补丁的内容并决定基于此内容进行选择或删除。
最好的git工具是什么?
我有一个包含此历史记录的存储库:
A---B---C---D
Run Code Online (Sandbox Code Playgroud)
然后,这个存储库被“拆分”(基本上,另一个存储库是使用 git-subtrees 创建的,它的历史从 'D' 开始)。
现在,我有这个历史的另一个回购:
# The same D as the other
D---E---F---G
Run Code Online (Sandbox Code Playgroud)
如何将同一项目故事情节的这两个“部分”合并到一个存储库中?
最终结果必须是:
A---B---C---D---E---F---G
Run Code Online (Sandbox Code Playgroud)
我已经尝试了很多东西,但所有这些都包括合并,这不是我想要的,因为合并不会保留一些更改,例如已删除的文件。
此外,我尝试为存储库的最后一个版本的所有更改生成补丁并将它们应用到旧版本中,但遇到了很多error: <file> already exists in index错误。
我发现这个问题,其他关于再养育一个承诺,那就是正是解决我的问题,两者的结合git replace --graft和git filter-branch。
现在我的任务完成了,我发布了下面问题的完整正确答案。
我有3家分店
开发,掌握和使用git flow feature start创建的功能分支。
现在,我想将由功能生成的提交合并到单独的修补程序中,这样就可以将其合并到master中,而无需将developer分支合并到master中。我该怎么做?
为了使
开发有100多个提交,这些提交是为单独发行的,
我从开发人员分支出来,并希望将其制作为单独的修补程序。
问题是hotix是一个主分支,因此如果我执行git merge功能,git会将所有开发人员提交与我对该功能的少数提交进行合并。
问题是。如何挑选功能?
编辑:
@Pigueiras
我更喜欢在这种情况下绘制图表。

我只需要将红色标注的提交从功能转移到修补程序即可。
git ×12
rebase ×5
git-rebase ×2
git-subtree ×2
git-branch ×1
git-flow ×1
git-history ×1
git-merge ×1
git-svn ×1
merge ×1
spam ×1
svn ×1