dcomitting

时间:2017-11-27 23:57:16

标签: git version-control git-svn

  

为长期问题道歉;我认为最好尽可能多地包含信息。

问题

如何使Gitlab托管的repo与(权威的)svn repo保持同步,并避免在使用git svn dcommit时重复提交?

设置

我在本地服务器上托管了一个svn存储库。远程团队(无权访问此服务器)正在使用git在存储库中开发软件的子树。出于商业目的,svn存储库被认为是用于发布等目的的权威。因此,我使用git-svn来保持团队同步。

存储库信息

  • "本地" svn repo at svn:// project
  • gitlab实例在gitlab.mydomain.com上运行
  • 我是唯一同时拥有svn和Gitlab帐户的用户; git用户没有svn帐户(或访问服务器),反之亦然
  

考虑上述安排是不可更改的,所以请不要提出其他安排。我对那些解决我特定的低级问题的答案很感兴趣,我保证很快就会问到这个问题=)

初始克隆

最初将存储库从svn克隆到Gitlab,如下所示:

git svn clone --prefix=svn --preserve-empty-dirs svn://project gitclone
git remote add origin https://gitlab/me/project.git
git push --set-upstream origin master

问题

当我在git分支上开发一个功能并将其集成回svn存储库时,我最终会在git commit历史记录中进行大量重复提交。 svn提交历史看起来很好。我已经确定这是因为回复到使用git svn dcommit创建的svn的提交具有与原始'不同的哈希值。承诺事情的git方面。这是一个示例流程:

git developer

$ git clone https://gitlab/me/project.git
$ git checkout -b git-f2
Switched to a new branch 'git-f2'

$ mkdir git-f2
$ touch git-f2/git-f2.txt
$ git add .
$ git commit -m "Add f2"
[git-f2 686a513] Add f2
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 git-f2/git-f2.txt

$ echo "some text" > f2/f2.txt
$ git commit -m "Update f2"
[git-f2 e84af9a] Update f2
 1 file changed, 1 insertion(+)

$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

$ git merge git-f2
Updating dc4d50b..e84af9a
Fast-forward
 git-f2/git-f2.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 git-f2/git-f2.txt

$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

$ git push
Counting objects: 8, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (8/8), 724 bytes | 0 bytes/s, done.
Total 8 (delta 0), reused 0 (delta 0)
To https://gitlab.mydomain.com/me/project.git
   dc4d50b..e84af9a  master -> master

我(回购同步器)

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

$ git fetch
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 8 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.
From https://gitlab.mydomain.com/me/project
   dc4d50b..e84af9a  master     -> origin/master

$ git status
On branch master
Your branch is behind 'origin/master' by 2 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)
nothing to commit, working tree clean

$ git pull
Updating dc4d50b..e84af9a
Fast-forward
 git-f2/git-f2.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 git-f2/git-f2.txt

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

此时,git log在我的(同步器)本地主服务器上显示与在远程服务器上相同的提交:

$ git log --format=oneline
commit e84af9ae738d782dfa5499cfb93b3dcb73cbf179 (HEAD -> master, origin/master)
commit 686a513eaf0083ad234e383f7e543df19431eff5
commit dc4d50bd66f36595d539c4f0c2ad70079c277315 (svn/git-svn)
commit 7e330320ac7d36331a8fb525f63fdf60f4ee070f

但是当我dcommit时,提交686a51e84af9会在我的本地主人身上再现新哈希(ed7b23605348):

$ git svn dcommit --use-log-author --add-author-from
Committing to svn://project ...
        A       git-f2/git-f2.txt
Committed r306
        A       git-f2/git-f2.txt
r306 = ed7b23e5abe29c09ff4483d811c1d645916e075b (refs/remotes/svn/git-svn)
        M       git-f2/git-f2.txt
Committed r307
        M       git-f2/git-f2.txt
r307 = 605348ec24142e2d382b295dbb34aa20c507fad9 (refs/remotes/svn/git-svn)
No changes between e84af9ae738d782dfa5499cfb93b3dcb73cbf179 and refs/remotes/svn/git-svn
Resetting to the latest refs/remotes/svn/git-svn

现在,我不再跟踪Gitlab大师了,而且很清楚原因:

$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 2 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean

$ git log --graph --format=oneline
* 605348ec24142e2d382b295dbb34aa20c507fad9 (HEAD -> master, svn/git-svn) Update f2
* ed7b23e5abe29c09ff4483d811c1d645916e075b Add f2
* dc4d50bd66f36595d539c4f0c2ad70079c277315 <redacted>
* 7e330320ac7d36331a8fb525f63fdf60f4ee070f <redacted>

$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 2 and 2 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working tree clean

此时,执行git pull会导致合并提交被添加到我的本地主服务器。后续的git push会留下以下图表:

$ git log origin/master --graph --format=oneline
*   e3bdac6d4fd58fbd006d777ceb3e87d31ee14ace (HEAD -> master, origin/master) GIT PULL Merge branch 'master' of https://gitlab.mydomain.com/me/project
|\
| * e84af9ae738d782dfa5499cfb93b3dcb73cbf179 Update f2
| * 686a513eaf0083ad234e383f7e543df19431eff5 Add f2
* | 605348ec24142e2d382b295dbb34aa20c507fad9 (svn/git-svn) Update f2
* | ed7b23e5abe29c09ff4483d811c1d645916e075b Add f2
|/
* dc4d50bd66f36595d539c4f0c2ad70079c277315 <redacted>
* 7e330320ac7d36331a8fb525f63fdf60f4ee070f <redacted>

svn日志和历史记录很好,所以我想知道是否有办法避免新的&#39;当我执行dcommit时,在我的本地主人上提交。这似乎可以避免我在这里看到的问题。或者,既然我是一个git新手,我可能完全错了!

2 个答案:

答案 0 :(得分:1)

简而言之,这是基于git提交的git svn dcommit dcommit对SVN repo的修订机制,然后重写git提交

git svn dcommit解释如下:

  
      
  • 将每个diff从当前分支直接提交给SVN   存储库,然后重新定位或重置(取决于是否   SVN和head之间存在差异。这将创建一个修订版   Git中每个提交的SVN。该命令将dcom更改为svn   基于git提交的repo
  •   
     

来自git svn document

     
      
  • 这将获取您在Subversion服务器上所做的所有提交   代码,为每个提交Subversion,然后重写您的本地   Git承诺包含唯一标识符。这很重要,因为   这意味着提交的所有SHA-1校验和都会发生变化。
  •   
     

来自Committing Back to Subversion

我们可以通过下面的图表说明:

在你的repo同步器和git svn dcommit之前从git remote repo中提取更改后,假设repo中的提交历史记录如下:

…---A---B---C---D---E  master, origin/master
            |
        svn/git-svn

执行git svn dcommit时,它会根据D之后的新提交Eremotes/svn/git-svn创建修订。它还将使用新的提交sha-1值重写提交DE(如下图中的提交D'E')。因此,在执行命令后,提交历史记录将为:

              D'---E'  master
             /
…---A---B---C---D---E  origin/master
            |
        svn/git-svn

因此git status会显示Your branch and 'origin/master' have diverged

由于您不想更改排列,您可以 git push -f origin master 强制推送到您的回购同步器中的GitLab回购。然后提交历史将是:

…---A---B---C---D'---E'  master, origin/master
            |
        svn/git-svn

答案 1 :(得分:0)

作为提交的一部分的所有元数据,如committer-name,commiter-e-mail,author-name,author-e-mail,commit-time,author-time,parent commit,commit-message等等都是SHA-1计算的一部分。

如果您向SVN dcommit发送内容然后从SVN更新(dcommit隐式执行此操作),您刚刚创建的新SVN提交将作为Git克隆中的新提交创建,包括提交者和作者信息来自实际的SVN提交,作者和提交时间来自实际的SVN提交和有关Git提交消息中SVN提交的git-svn元数据(最后一行)。这当然会创建一个新的Git提交,它具有相同的更改但是具有不同的SHA-1值。

因此你总是需要将你在Git中完成的工作重新安装到SVN的新移植提交中,这将丢弃引入与SVN提交相同更改的Git版本。在当前的设置中没有其他方法可以解决这个问题。

对于像你这样的情况,SubGit提供了SVN存储库的Git镜像,并允许并行使用Git和SVN,并自动进行同步。我没有使用它的经验,但我不知道这是否也适用于SVN存储库的子树。