如果有多个未推送的 git
提交记录,是否可以只将其中一个提交记录 git-svn dcommit
到SVN仓库?
例如,我有提交记录foo、bar和baz,但现在我只想将bar提交记录上传到svn仓库。这是否可行?
(以下假设您的工作在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
最后一步是变基操作,以使得 master
与 svn 同步:
git svn rebase
我有点不太清楚为什么需要这样做,但我猜测在分离 HEAD 状态下提交可能与此有关。
git svn dcommit -n
或--dry-run
是完美的使用案例。 - hdlgit svn dcommit无法选择性提交bar。如果您直接在主分支上提交了foo、bar和baz,则需要执行以下操作才能仅将bar提交到svn。
假设bar的提交sha类似于13abc...
而git log master显示了您的3个提交foo、bar和baz。
您需要从master创建一个分支
git branch wip
wip分支现在具有foo、bar和baz
将主分支的head重置为foo、bar或baz之前的提交。您可以使用git reset(阅读手册,hard、soft和mixed选项之间的差异会影响工作树中未提交的更改)
git reset --hard(foo、bar、baz之前的COMMIT-ID)
(或者)
git reset --hard HEAD~3(返回3个版本)
现在您的主分支没有foo、bar或baz。使用git log进行验证。
现在,您可以从wip分支中挑选要提交到svn的提交。所以要得到bar
git cherry-pick wip 13abc(bar提交的sha)
主分支只获取bar提交。
建议未来使用
因此,对于 git-svn,最好不要直接在跟踪远程 svn 的主分支上进行提交。在本地分支上完成您的工作,并在 dcommit 之前有选择性地合并到主分支。
cherry-pick
到新分支上,接着git-svn dcommit
该分支,并在完成后删除它。但是这种方法并不太优雅。如果主分支已经有了这些提交,你可以像Sizzler建议的那样重置head。
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
有时候我只想提交我的分支里的几个commit,例如:
A-----B-----C------D
^ ^
| |
svn/trunk trunk
B
和C
但不想提交D
,我会创建一个新分支,执行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不会导致冲突。
附注:我经常省略新分支并只是检出分离的。例如:
git checkout --detach C
git svn dcommit
git checkout trunk
git svn rebase
git-svn-id
。 - René Link