拆分git分支或按文件类型

时间:2016-07-25 21:57:22

标签: git

我有一个包含html和javascript代码的分支。出于横切原因,我需要首先向html提交质量更改,然后再提交js。目前,我有一个分支,对其进行了两种更改。

如何按文件类型将提交分为两个较小的提交(或分支)?

2 个答案:

答案 0 :(得分:3)

您无法更改现有提交,但可以进行新提交,其父级与现有提交的提交相同#34;提交太多"提交。

在开始之前,请确保您有一个干净的工作树("无需承诺")。那样没有git reset或任何东西都可能失去任何东西。如有必要,您可以进行新的提交,以便您可能需要zorg~2而不是zorg~1(请参见下图)。您稍后可以从此提交中检索已保存的项目。

画出你现在拥有的东西

与Git一样,首先绘制(至少部分)你的提交图。你现在在某个分支上,这意味着你有分支 name 指向最尖端的提交,并且该提交指向一些父提交,依此类推:

...--A--B--C--D   <-- zorg

其中zorg是您当前的分支,大概是D这是太大的提交而C是它之前没有任何更改集的提交。 (如果你不得不再做一些提交,或许提交D是一步或多步;如果是,请调整下面的数字。)

提示:使用git log --graph --oneline --decorate(有或没有--all)让Git为你绘制图形(虽然它垂直绘制,顶部有更多近期的东西,而不是水平向右边的新东西。)

绘制喜欢的内容

您无法更改D,但可以进行新的提交EF,您可以这样安排:

...--A--B--C--D     <-- ... we'll fill this in later ...
            \
             E--F   <-- ... likewise this ...

或者这样:

             F      <-- ...
            /
...--A--B--C--D     <-- ...
            \
             E      <-- ...

提交D将继续成为您的&#34;太大&#34;提交虽然E可能只有HTML更改而F可能只有JS更改。 (如果F构建在E上,那么它确实有两个更改,实际上就内容而言提交D。如果F构建在C上然后它只有 JS的变化。由你来决定如何安排这些。)

每个...都要用分支名称填写。您可以单独保留现有的分支名称,并创建一个或两个新的分支名称,这是我首先显示的名称。

手动执行

我们假设您想要两个新的分支名称,EF各自拥有C作为其父级(因此,不是 C--E--F)。 Git是Git,有很多方法可以做到这一点,但一个简单的方法就是使用git checkout -b创建它们,这会创建新的分支名称并切换到它们(以便git status说你&#39} ;重新开始新的分支)。此git checkout -b命令还采用可选的提交说明符,这是在创建新分支后在索引和工作树中具有的提交。我们希望EF都来自C,因此我们希望创建新的分支&#34; at&#34;提交C

git checkout -b zorg-html zorg~1

名称zorg标识提交D。添加~后缀意味着来自此提交的#34;退回到第一个父链接,但是我多次在数字&#34;中说。由于该数字是1(一),我们将退回一个父母,这将我们从D带到C。这意味着名称zorg-html目前将指向提交C,我们将在此新分支上。

现在我们已经zorg-html(在提交C),我们只想替换所有HTML文件。这些文件的正确版本位于提交D中,如名称zorg所指向的那样。获取这些文件的简单方法是:

git checkout zorg -- first_file second_file third_file ...

这对git checkout有点疯狂 - 这次根本不会更改分支,而只是提取特定的命名文件(文件名列表)来自指定提交(--的{​​{1}}部分之后),即提交zorg)。

如果这些文件都以D结尾,而且.html文件实际上不是HTML文件,这种简单方法的简单版本是:

.html

也就是说,从顶级目录中获取名为git checkout zorg -- '*.html' '**/*.html' 的每个文件,并从whatever.html提交中提取任意数量的子目录中名为whatever.html的每个文件(提交) zorg,再次)。

这种D将更新的文件写入索引和工作树,因此此时您只需git checkout结果。

现在,要创建提交git commit,我们重复整个过程:

F

(假设,与之前的HTML文件一样,每个JS文件都被命名为git checkout -b zorg-js zorg~1 # new zorg-js branch starting at C git checkout zorg -- '*.js' '**/*.js' git commit ,而没有名为.js的文件是其他而不是JS文件。现在我们有:

.js

显然,您可以为所有这些分支选择更好的名称。

如果您希望在提交 F <-- zorg-js / ...--A--B--C--D <-- zorg \ E <-- zorg-html 之后进行提交F,只需省略将创建新分支的E并切换回提交git checkout -b。当您提取所有C文件并生成提交zorg-html时,这将使您在提交E的分支.js上,以便F&#39; s父母将是F,您将拥有:

E

如果你想要的只是一些简单的食谱,你可以在这里停下来。如果您想学习很多方法来解决这个问题和其他问题,请继续阅读。

如果您想要...--A--B--C--D <-- zorg \ E--F <-- zorg-html # zorg-html is clearly a bad name 本身E--F怎么办?

没问题。 Git是Git,有多种方法可以做到这一点。例如,您可以在开始之前重命名zorg

zorg

现在你有了这个:

git branch -m zorg gary-oldman

您可以安全地创建新的A--B--C--D <-- gary-oldman

当然,任何上游设置都坚持使用重命名的分支。没什么大不了的,您可以使用zorg为每个分支设置新的上游。

当然,Git是Git,还有另外一种方法!您可以创建一个新的分支名称​​ now ,指向提交git branch --set-upstream-to,只要您需要它就可以记住它 - 您需要它来为两个{{1} }命令。然后,您可以D分支名称git checkout,以便它指向提交git reset

zorg

现在,当您进行新的提交时,他们会将名称C向前移动,但名称git checkout zorg # make sure zorg is the current branch git branch temp # save its tip commit under a new name git reset --hard zorg~1 # and move zorg back to commit C 仍将为您记住提交zorg

temp

现在要访问提交D,您将使用名称A--B--C--D <-- temp \ E <-- zorg ,并重新查找提交D,您将使用temp

请注意,如果您有额外的提交&#34;过去&#34; C(例如,用于保存HTML和JS更改后完成的工作):

temp~1

你仍然可以做到这一切。它就是现在,要命名提交D,您将需要其SHA-1哈希&#34;真名称&#34; (这永远不会改变,但真的难以正确输入 - 鼠标剪切和粘贴在这里很有帮助),或从小费倒计时。此处A--B--C--D--H--I--J <-- temp, or zorg, or whatever 可能将提交命名为Ctemp提交Jtemp~1I;因此,temp~2Htemp~3D。一旦你完成了分割提交,你就可以挑选剩余的提交。

使用temp~4

Git是Git,还有另一种方法可以做到这一点,如果在C之后提交,则提交拆分尤其有用。这个特别的需要Git的一些安慰,但最终是最短和最快的方法。我们从git rebase -i开始将提交D(以及任何后来的提交)重新绑定到git rebase -i,它已经(或者它们已经存在);但我们将D的{​​{1}}行更改为C

Git现在让我们进入了已经提交了pick的rebase会话。现在我们想要D(或edit; D只是默认值)返回提交git reset HEAD~1。这将设置当前提交 - 我们处于分离的HEAD模式,因此这只是将git reset --mixed HEAD~1本身调整为--mixed并重置索引以匹配C,但保留了工作 - 树设置为HEAD。现在我们只选择C我们想要的文件:所有C个文件。使用您喜欢的任何方法(例如Dgit add)添加这些方法,并.html结果。然后find ... | xargs git add剩下的文件再次git add '*.html' '**/*.html',然后再git commit复制剩余的提交,并将分支标签移动到最末端的提交。

答案 1 :(得分:0)

我从this answer

一起攻击了它
git checkout -b new-branch # checkout from master
git diff big-branch --name-only -- '*.html' | xargs git checkout html-comments-take-two --

如果文件名中有空格,可能需要传递给sed 's, ,\\&,g'

我无法使用**/*.html样式路径规范让它工作,我不知道为什么。

相关问题