26

给定多个未推送的git提交,是否可以git-svn dcommit只进行其中一个提交?

例如,我有提交 foo、bar 和 baz,但现在我只想让 bar 出现在 svn 存储库中。这可能吗?

4

4 回答 4

27

(以下假设您的工作在master.)

首先,重新排序你的最后三个提交,以便它bar是第一个。

git rebase -i HEAD~3

编辑器会弹出如下内容:

pick 498e4f4 foo
pick 71547ae bar
pick abf09c6 baz

# Rebase 4d3fe72..abf09c6 onto 4d3fe72
#
# ...

在弹出的编辑器中重新排序它们,以便bar首先出现。

pick 71547ae bar
pick 498e4f4 foo
pick abf09c6 baz

# Rebase 4d3fe72..abf09c6 onto 4d3fe72
#
# ...

Git 将旋转几秒钟并弹出确认信息:

Successfully rebased and updated refs/heads/master.

现在您可以暂时回滚到bar提交(HEAD~2意味着从 两次提交HEAD)并 dcommit 它:

git checkout HEAD~2
git svn dcommit

如果你像我一样偏执,你可以git svn dcommit -n先确保你只做你想做的事。

现在跳回master

git checkout master

最后一点是 rebase 以便master与 svn 同步:

git svn rebase

为什么需要这样做对我来说有点模糊,但我猜想 dcommitting 处于分离的 HEAD 状态与它有关。

于 2011-11-30T15:22:18.147 回答
13

git svn dcommit 不能选择性地提交吧。如果您在 master 分支上直接提交了 foo、bar 和 baz,那么您必须执行以下操作才能在 svn 中仅获取 bar。

假设 bar 的提交 sha 类似于 13abc ...

git log master 会显示你所有的 3 次提交 foo、bar 和 baz。

  • 你需要从master创建一个分支

    git 分支 wip

wip 分支现在有 foo、bar 和 baz

  • 在 foo、bar 或 baz 之前将 master 的头部重置为提交。您可以使用git reset来做到这一点(阅读手册,硬、软和混合选项之间的差异会影响工作树中未提交的更改)

    git reset --hard(在 foo、bar、baz 之前的 COMMIT-ID)

    (或者)

    git reset --hard HEAD~3(返回 3 个修订版)

现在你的主分支没有 foo、bar 或 baz。用 git log 验证。

  • 现在你可以只挑选你想从 wip 分支提交到 svn 的提交到 master 中。所以得到吧

    git cherry-pick wip 13abc(酒吧提交的sha)

主人只能单独获得酒吧提交。

  • 现在 git svn dcommit 应该单独推 bar 。

建议未来使用

所以对于 git-svn,最好不要直接在跟踪远程 svn 的 master 分支上提交。在本地分支上做你的工作,并在 dcommiting 之前有选择地合并到 master。

于 2009-08-12T13:22:28.187 回答
4

我有一种严厉的答案。您可以创建一个没有 foo、bar 和 baz的新分支,然后将cherry-pickbar 转到新分支,然后git-svn dcommit是该分支,完成后将其删除。不过,这似乎不是很优雅。

所以假设 foo、bar 和 baz 在分支 x 中,而 master 没有它们。

git branch y master

git checkout y

git cherry-pick <sha1 of bar>

git svn dcommit

git checkout x

git svn rebase

git branch -d y

如果 master 确实有这些提交,您可以按照 Sizzler 的建议重置头部。

于 2009-08-10T17:36:29.540 回答
2

我有时只想提交我的分支的一些提交。例如

A-----B-----C------D  
^                  ^
|                  |
svn/trunk          trunk

如果我想提交BC不想D创建一个新分支,请执行 a svn dcommit,切换回trunk并删除该分支。

当我在分支时trunk,我做

git checkout -b temp `C`
git svn info // just to check that branch temp is properly connected to svn
git svn dcommit
git checkout trunk
git branch -D temp

编辑

就像 Stefan 评论的那样:

加上一个额外的“git svn rebase”,它对我来说效果很好。

这是必要的,因为提交到 svn 的提交将被重写。git-svn将 添加git-svn-id到提交消息中,因此即使提交的内容相同,提交哈希也会更改。但由于内容相同,rebase 不会引起冲突。

PS:我也经常省略新的分支,只是结帐分离。例如

git checkout --detach C
git svn dcommit
git checkout trunk
git svn rebase 
于 2015-10-13T13:55:22.187 回答