为长期问题道歉;我认为最好尽可能多地包含信息。
如何使Gitlab托管的repo与(权威的)svn repo保持同步,并避免在使用git svn dcommit
时重复提交?
我在本地服务器上托管了一个svn存储库。远程团队(无权访问此服务器)正在使用git在存储库中开发软件的子树。出于商业目的,svn存储库被认为是用于发布等目的的权威。因此,我使用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 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
时,提交686a51
和e84af9
会在我的本地主人身上再现新哈希(ed7b23
和605348
):
$ 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新手,我可能完全错了!
答案 0 :(得分:1)
简而言之,这是基于git提交的git svn dcommit
: dcommit对SVN repo的修订机制,然后重写git提交。
git svn dcommit
解释如下:
- 将每个diff从当前分支直接提交给SVN 存储库,然后重新定位或重置(取决于是否 SVN和head之间存在差异。这将创建一个修订版 Git中每个提交的SVN。该命令将dcom更改为svn 基于git提交的repo
- 这将获取您在Subversion服务器上所做的所有提交 代码,为每个提交Subversion,然后重写您的本地 Git承诺包含唯一标识符。这很重要,因为 这意味着提交的所有SHA-1校验和都会发生变化。
我们可以通过下面的图表说明:
在你的repo同步器和git svn dcommit
之前从git remote repo中提取更改后,假设repo中的提交历史记录如下:
…---A---B---C---D---E master, origin/master
|
svn/git-svn
执行git svn dcommit
时,它会根据D
之后的新提交E
和remotes/svn/git-svn
创建修订。它还将使用新的提交sha-1值重写提交D
和E
(如下图中的提交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存储库的子树。