我有一个分支develop
,并从中分支了一个名为next
的大功能。
在next
中,有一个连续的流程来编辑最初来自develop
的文件,以及仅在next
中创建新文件的文件。
TL; DR:您可以跳过下一部分直接转到问题。
(a)next
对从develop
继承的文件的更改始终是向后兼容的,并且始终在那里提交。
(b)与此同时,develop
本身也正在发展,这些变化也应该在next
中可见。因此,next
时不时会develop
重新定位。
提交回develop
导致合并冲突,因为(b)和rebase导致合并冲突,因为(a)。后者可以通过-X theirs
来修复,因为冲突已经在第一步中解决了。
但这效率不高。
有没有办法自动:
develop
)next
)可能的复杂解决方案
我可以想象一些'简单'(r)git-foo是可能的,因为这个愿望并不是唯一的。但如果没有,可能会有一些bash
脚本。例如,以下命令:
git ls-tree -r develop --name-only
将显示确实位于develop
的文件列表。不在该列表中的文件只能在next
。
我想如果所有其他方法都失败了,我可以创建一个shellcript来:
develop
上存在的所有文件提交到develop
next
next
develop
醇>
但它并不像听起来那么简单。
答案 0 :(得分:1)
与往常一样,我会首先建议您在#34;之前绘制(已知)"和(#);"""首先提交图形。好吧,也许第二个:第一个,决定是否要允许这些操作使用"脏工作树"和/或"脏指数" (与当前HEAD
,提交不匹配的那个。
但是,在这种情况下,您可能希望使用有关每个中所需的快照tree
对象的辅助标记来扩充图形,尤其是有关如何处理(现有)提交中的文件的示例问题,vs整个过程开始时可能在索引和/或工作树中的文件。这可能有助于决定如何(根据Git机制和可编写脚本的命令)继续进行。
一旦你掌握了这些,请记住,Git是你可以随意使用的一大盒工具。这些工具包括以下功能:
new 提交作为其父级,无论提交是HEAD
还是当时索引中的任何提交作为其树。但是还要看git commit -a
,它将从工作树中获取索引中路径已经的文件的新文件版本,或者从工作中缺少的索引路径中删除-tree。
当然,仅在索引或工作树中的文件很容易被删除。提交现有索引使其与任何提交一样永久(见下文)。所以一般来说,如果你有未提交的工作,首先要做的就是提交它。新提交将旧提交作为其父提交,新提交现在位于HEAD
- 或者通常位于HEAD
引用的分支名称中(以便git rev-parse HEAD
找到新ID,但含义 git rev-parse refs/heads/next
或其他任何内容。
分支名称只是指向提交提交。然后每个提交指回其直接父级(或者用于合并提交,父级,复数)。以命名 tip 提交结束的提交链也称为分支(请参阅What exactly do we mean by "branch"?)。您可以使用分离的HEAD进行没有名称尚未的新提交,如果方便的话:您只需要将ID保存在某处(使用git rev-parse HEAD
创建它们,例如,将ID复制到shell变量中,以便您可以命名它们。你必须在两周的默认修剪期限内给它们永久名称 - 通常是分支名称 - 以防止它们被垃圾收集所收获。
git stash
,如果您选择使用它,可以将当前索引保存为提交,然后将当前工作树保存为另一个提交,然后选择保存未跟踪,甚至未跟踪 - 并忽略,将文件作为第三个提交。这三个提交都不在任何分支上;相反,特殊名称refs/stash
指向这些两个或三个提交中的一个(然后用于查找其他提交,以及HEAD
在git stash
同时进行的提交git rebase
或所有这三个)。这些提交不参与git stash
。如果您需要干净的工作树和/或索引,则无需使用git rebase --onto target limit
及其复杂功能。如果没有,你可能想要它,或做类似的事情。
运行limit..HEAD
将复制--cherry-pick --right-only --no-merges limit...HEAD
选择的提交(但通常会丢弃合并和预先选择的提交,即这确实使用-m
,但具体情况有所不同还有一些类型的rebase,包括-i
,-k
,-p
和target
参数(如果给出的话)。 limit
默认为 <upstream>
参数提供的提交(rebase文档调用develop
)。通常这是恰当和充分的;在您的情况下可能会或可能不会,这取决于您添加提交的方式和时间。
所有这一切,我之前已经处理过类似的事情,我将描述我更喜欢这样做的方式。这是否适合你是另一个问题。
你有一个&#34;基础分支&#34;,在你的情况next
,我假设一个更大的团队正在努力。你还有一个功能或主题分支(你称之为project/0
,但我通常会给出一个更具体的名称,project-mac
or whatever(虽然我自己从来没有在麻省理工学院......)。我所做的是编号我的分支。
project-0
(或git checkout -b project/0 develop
,我并不一致):我的第一次刺伤。这基本上是project/1
,然后破解并提交一段时间。
project-1
(或git rebase
):一些经验教训,我&#34; rebase&#34;在当前的主要分支上,通过挑选或重写或其他。通常在0到1之间,没有足够的可挽救代码来打扰像project/2
这样的工具。
现在有些部分已经足够扎实了,我自己提交进入主分支(并根据工作等情况,让他们审核或通过测试或其他)。现在我在Git中做git checkout -b project/2 project/1
git rebase develop
:
develop
这会自动抛出已经完全被git log project/1
(由我作为第3步的第一部分)挑选出来的提交,并且给我合并冲突的部分是&#34;不干净的挑选& #34;或者与我解决的其他工作发生冲突。在困难的情况下,我可以轻松git show
和{{1}}来自那里的具体提交,如果我需要记住我做了什么以及为什么我这样做。如果我对提交消息很满意,那么它们就是必要的提醒。
冲洗并重复恶心。
请注意,这些分支实际上都不会被重新定位,除非在初始步骤中从旧版本创建新的编号风味。这意味着它们可以轻松地在多个克隆之间共享,这在必须在不同操作系统上测试或分布在多个人之间时非常有用。
答案 1 :(得分:0)
必须分多步完成。提交next
,然后重新绑定和/或合并以将所有内容重新导入develop
。 Git没有能力一次性完成这项工作
答案 2 :(得分:0)
我知道没有内置这样做的方法,虽然我会想象这很受欢迎。所以我去了一些bash
黑客并想出了这个。
注意,只有在进行更改之前重新进行重新定位时,这只会在没有合并冲突的情况下有效。
为了分隔哪些文件应该提交给父(develop
)分支以及哪些文件应该提交给功能(next
),这些是最重要的命令:
git ls-files -mdo --exclude-standard
develop
)中存在的所有文件:
git ls-tree -r develop --name-only
sort <(git ls-tree -r develop --name-only | sort) <(git ls-files -mdo --exclude-standard | sort) | uniq -d
所以我们想要做的是:
develop
)的sort <(git ls-tree -r develop --name-only | sort) <(git ls-files -mdo --exclude-standard | sort) | uniq -d | xargs git add
next
)。但保留暂存的文件
git stash --keep-index -u
develop
)
git stash
develop
)git checkout develop
git stash pop
git commit -am "<commit message>"
next
)
git checkout next
git stash pop
git add -A
git commit -m "<commit message>"
git rebase develop
完成! develop
和next
现在都使用最新代码进行更新。
如果您保证不重命名文件,您可以放心地将其放入脚本中以自动执行此操作。
mergedowncommit.sh
:
#!/usr/bin/env bash
# By Redsandro (http://www.Redsandro.com/)
# 2017-03-03
if [ -z "$3" ]; then
echo "No commit message supplied."
echo "Usage: mergedowncommit.sh <parent> <feature> <commit message>"
exit 1
fi
sort <(git ls-tree -r "$1" --name-only | sort) <(git ls-files -mdo --exclude-standard | sort) | uniq -d | xargs git add
git stash --keep-index -u
git stash
git checkout "$1"
git stash pop
git commit -am "$3"
git checkout "$2"
git stash pop
git add -A
git commit -m "$3"
git rebase "$2"
if [ $? -eq 0 ]; then
echo "Looks like it worked. :)"
else
echo "Looks like some files were not freshly rebased prior to running this script."
echo "Please manually solve merge conflicts, and run \"git rebase --continue\"."
fi
用作:
mergedowncommit.sh <parent> <feature> <commit message>
E.g:
mergedowncommit.sh develop next "This is my commit message"
您可以根据自己的工作流程进行调整。也许添加您最喜欢的difftool来解决合并冲突。我可以想象,当develop
也处于工作状态时,你至少有一个,它包含一个包含版本信息的文件。
注意:使用风险自负。