Git导出/导入提交历史记录

时间:2016-07-09 12:55:51

标签: git repository export gitlab devops

我会尽量简单......

放手:

我们有一个大的git repo,其中包含3个不同项目的文件夹:

主要仓库中的文件夹结构:

existing_repo
      ├── .net_is_dir
      ├── java_is_dir
      └── android_is_dir
对于java,

对于一个问题,我们在root中有分支

对于android dir,每一个问题,我们在分支“android”中继承了分支。在gitlab结构中是下一个:

回购中的分支结构

existing_repo
      ├── .net_dev
      ├── .net_qa
      |
      ├── java_dev
      ├── java_qa
      ├── java_issue_1
      ├── java_issue_n
      |
      ├── android_dev
      ├── android_qa
      └── android
           ├─ android_issue_1
           └─ android_issue_n

任务是文字:

  • 我需要为3个不同的项目创建3个新的回购
  • .net_newrepo
  • java_newrepo
  • android_newrepo

  • 每个项目的文件应该是root(用于CI),而不是在子目录中。

  • 应以正确的方式导出/导入分支:

    issue1_4_java - > java_newrepo / issue1_4_java

    android / issue1_4_android - > android_newrepo / issue1_4_android

  • 新项目应仅包含特定项目的历史记录。 .net关于.net,而不是关于ios和android等。

我认为这是不真实的 我的工作手册是

1)在新的特定仓库中导入现有仓库,移动目录,删除无用的 - >导致:

每个项目都将包含所有旧项目,回购将很大

2)创建具有所需分支的新回购,只需将文件从appropriare dirs复制到新分支并提交 - >导致

没有历史,回购规模很小

可能你会建议我一些新的想法?

2 个答案:

答案 0 :(得分:1)

让我们尝试一下。这有点实验性,需要你跳进去。请原谅我使用" dotnet"而不是" .net"在下面。

$ cp -r existing_repo dotnet_newrepo # Get a copy of the existing repo. The new directory will ultimately be the repo for dotnet.
$ cd dotnet_newrepo # Go to the new directory for dotnet.
$ git remote rm origin # Remove the "origin" remote. Do this for all remotes.
$ cd .. # Go back.
$ cp -r dotnet_newrepo java_newrepo # Get a copy for java (without remotes).
$ cp -r dotnet_newrepo android_newrepo # Get a copy for android (without remotes).

现在你有三个git repos," dotnet_newrepo"," java_newrepo"," android_newrepo",它们就像你现有的仓库,只有没有遥控器。继续前进。

$ cd dotnet_newrepo
$ git filter-branch --subdirectory-filter dotnet_is_dir -- --all
$ cd ..
$ cd java_newrepo
$ git filter-branch --subdirectory-filter java_is_dir -- --all
$ cd ..
$ cd android_newrepo
$ git filter-branch --subdirectory-filter android_is_dir -- --all
$ cd ..

上面的每个git filter-branch命令都将通过repo的所有(因为--all)分支并重写其历史记录,但是......

  

仅查看触及给定子目录的历史记录。该   结果将包含该目录(并且仅包含该项目)作为其项目   根

(来自git-filter-branch documentation

换句话说,子目录的内容将转到repo的根目录,git历史记录将被重写,以便它只包含与该子目录相关的历史记录,其内容最终将是根目录的新内容。

按照上述步骤,您仍应在每个仓库中拥有所有分支(均具有重写历史记录)。对于每个仓库,您应该删除不相关的分支,并根据您的新约定重命名相关分支。如果分支的数量非常大,您可以使用脚本。最后,在为每个新仓库修复分支并在创建相应的远程仓库(例如在GitLab中)之后,您可以将其添加为远程并随意推送。

答案 1 :(得分:0)

似乎通过使用命令

解决了问题
git filter-branch --subdirectory-filter android_is_dir -- --all

谢谢@xnakos耐心等待。此外,在此期间我重命名了分支,使用特殊键(谷歌搜索)和每个新分支我分开推,现在看起来很棒,开发团队明天会很开心)))

BTW直到凌晨3点我制作剧本,由于它没有用,我看到每个分支的所有历史记录,我没看到分支之间的关系(合并)

可能有人会发现它很有趣, 脚本充满了拐杖和硬编码,但无论如何,它对我有用)

#!/usr/bin/python

import os
import json
import shutil
import subprocess
from distutils.dir_util import copy_tree

old_repo = "/home/ostetsia/coding/java"
old_repo_dir = "/home/ostetsia/coding/java/java_subdir"
new_repo = "/home/ostetsia/coding/java

old_repo_branch = "java/java_case_number"
new_repo_branch = "java_case_number"

#changing branch in new repo
os.chdir(new_repo)

try:
    subprocess.check_output(["git", "branch", new_repo_branch])
except:
    print "branch {0} exist in new repo".format(new_repo_branch)

subprocess.check_output(["git", "checkout", new_repo_branch])

os.chdir(old_repo)

try:
    subprocess.check_output(["git", "branch", old_repo_branch])
except:
    print "branch {0} exist in old repo".format(old_repo_branch)

os.chdir(old_repo)
subprocess.check_output(["git", "checkout", old_repo_branch])


git_add = "git add *"
git_old_log = subprocess.check_output(['git', 'log', '--reverse', '--pretty=format:{"hash": "%H", "reporter":"%an", "mail": "%ce", "date": "%cd", "comment": "%s"}'])
commit_list = {}

i=0
for data_line in git_old_log.split('\n'):
    i+=1
    data_line = json.loads(data_line)
    commit_list[i] = dict(data_line)

git_old_log_count_commint = i


for commit, data in commit_list.iteritems():

    for key, value in data.iteritems():

        if key == "date":
            date=value
            print date
        elif key == "mail":
            mail = value
        elif key == "hash":
            hash = value
        elif key == "comment":
            comment = value
        elif key == "reporter":
            reporter = value

    git_commit_command = "git commit -a --author='{0} <{1}>' --date='{2}' -am '{3}'".format(reporter, mail, date, comment)
    #print git_commit_command

    os.chdir(new_repo)
    os.system("pwd")
    os.system("rm -rf")
    print commit
    os.chdir(old_repo)
    subprocess.check_output(["git", "checkout", hash])


    copy_tree(old_repo_dir, new_repo)

    os.chdir(new_repo)
    os.system(git_add)
    os.system(git_commit_command)
    print os.getcwd()