How to move git repository with all branches from bitbucket to github?

前端 未结 11 1765
孤城傲影
孤城傲影 2020-12-02 03:21

What is the best way to move a git repository with all branches and full history from bitbucket to github? Is there a script or a list of commands I have to use?

11条回答
  •  失恋的感觉
    2020-12-02 04:01

    I realize this is an old question. I found it several months ago when I was trying to do the same thing, and was underwhelmed by the answers given. They all seemed to deal with importing from Bitbucket to GitHub one repository at a time, either via commands issued à la carte, or via the GitHub importer.

    I grabulated the code from a GitHub project called gitter and modified it to suite my needs.

    You can fork the gist, or take the code from here:

    #!/usr/bin/env ruby
    require 'fileutils'
    
    # Originally  -- Dave Deriso        -- deriso@gmail.com
    # Contributor -- G. Richard Bellamy -- rbellamy@terradatum.com
    # If you contribute, put your name here!
    # To get your team ID:
    # 1. Go to your GitHub profile, select 'Personal Access Tokens', and create an Access token
    # 2. curl -H "Authorization: token " https://api.github.com/orgs//teams
    # 3. Find the team name, and grabulate the Team ID
    # 4. PROFIT!
    
    #----------------------------------------------------------------------
    #your particulars
    @access_token = ''
    @team_id = ''
    @org = ''
    
    
    #----------------------------------------------------------------------
    #the verison of this app
    @version = "0.2"
    
    #----------------------------------------------------------------------
    #some global params
    @create = false
    @add = false
    @migrate = false
    @debug = false
    @done = false
    @error = false
    
    #----------------------------------------------------------------------
    #fancy schmancy color scheme
    
    class String; def c(cc); "\e[#{cc}m#{self}\e[0m" end end
    #200.to_i.times{ |i| print i.to_s.c(i) + " " }; puts
    @sep = "-".c(90)*95
    @sep_pref = ".".c(90)*95
    @sep_thick = "+".c(90)*95
    
    #----------------------------------------------------------------------
    # greetings
    
    def hello
      puts @sep
      puts "BitBucket to GitHub migrator -- v.#{@version}".c(95)
      #puts @sep_thick
    end
    
    def goodbye
      puts @sep
      puts "done!".c(95)
      puts @sep
      exit
    end
    
    def puts_title(text)
       puts  @sep, "#{text}".c(36), @sep
    end
    
    #----------------------------------------------------------------------
    # helper methods
    
    def get_options
      require 'optparse'
    
      n_options = 0
      show_options = false
    
      OptionParser.new do |opts|
        opts.banner = @sep +"\nUsage: gitter [options]\n".c(36)
        opts.version = @version
        opts.on('-n', '--name [name]', String, 'Set the name of the new repo') { |value| @repo_name = value; n_options+=1 }
        opts.on('-c', '--create', String, 'Create new repo') { @create = true; n_options+=1 }
        opts.on('-m', '--migrate', String, 'Migrate the repo') { @migrate = true; n_options+=1 }
        opts.on('-a', '--add', String, 'Add repo to team') { @add = true; n_options+=1 }
        opts.on('-l', '--language [language]', String, 'Set language of the new repo') { |value| @language = value.strip.downcase; n_options+=1 }
        opts.on('-d', '--debug', 'Print commands for inspection, doesn\'t actually run them') { @debug = true; n_options+=1 }
        opts.on_tail('-h', '--help', 'Prints this little guide') { show_options = true; n_options+=1 }
        @opts = opts
      end.parse!
    
      if show_options || n_options == 0
        puts @opts
        puts "\nExamples:".c(36)
        puts 'create new repo: ' + "\t\tgitter -c -l javascript -n node_app".c(93)
        puts 'migrate existing to GitHub: ' + "\tgitter -m -n node_app".c(93)
        puts 'create repo and migrate to it: ' + "\tgitter -c -m -l javascript -n node_app".c(93)
        puts 'create repo, migrate to it, and add it to a team: ' + "\tgitter -c -m -a -l javascript -n node_app".c(93)
        puts "\nNotes:".c(36)
        puts "Access Token for repo is #{@access_token} - change this on line 13"
        puts "Team ID for repo is #{@team_id} - change this on line 14"
        puts "Organization for repo is #{@org} - change this on line 15"
        puts 'The assumption is that the person running the script has SSH access to BitBucket,'
        puts 'and GitHub, and that if the current directory contains a directory with the same'
        puts 'name as the repo to migrated, it will deleted and recreated, or created if it'
        puts 'doesn\'t exist - the repo to migrate is mirrored locally, and then created on'
        puts 'GitHub and pushed from that local clone.'
        puts 'New repos are private by default'
        puts "Doesn\'t like symbols for language (ex. use \'c\' instead of \'c++\')"
        puts @sep
        exit
      end
    end
    
    #----------------------------------------------------------------------
    # git helper methods
    
    def gitter_create(repo)
      if @language
        %q[curl https://api.github.com/orgs/] + @org + %q[/repos -H "Authorization: token ] + @access_token + %q[" -d '{"name":"] + repo + %q[","private":true,"language":"] + @language + %q["}']
      else
        %q[curl https://api.github.com/orgs/] + @org + %q[/repos -H "Authorization: token ] + @access_token + %q[" -d '{"name":"] + repo + %q[","private":true}']
      end
    end
    
    def gitter_add(repo)
      if @language
        %q[curl https://api.github.com/teams/] + @team_id + %q[/repos/] + @org + %q[/] + repo + %q[ -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ] + @access_token + %q[" -d '{"permission":"pull","language":"] + @language + %q["}']
      else
        %q[curl https://api.github.com/teams/] + @team_id + %q[/repos/] + @org + %q[/] + repo + %q[ -H "Accept: application/vnd.github.v3+json" -H "Authorization: token ] + @access_token + %q[" -d '{"permission":"pull"}']
      end
    end
    
    def git_clone_mirror(bitbucket_origin, path)
      "git clone --mirror #{bitbucket_origin}"
    end
    
    def git_push_mirror(github_origin, path)
      "(cd './#{path}' && git push --mirror #{github_origin} && cd ..)"
    end
    
    def show_pwd
      if @debug
        Dir.getwd()
      end
    end
    
    def git_list_origin(path)
      "(cd './#{path}' && git config remote.origin.url && cd ..)"
    end
    
    # error checks
    
    def has_repo
      File.exist?('.git')
    end
    
    def has_repo_or_error(show_error)
      @repo_exists = has_repo
      if !@repo_exists
        puts 'Error: no .git folder in current directory'.c(91) if show_error
        @error = true
      end
      "has repo: #{@repo_exists}"
    end
    
    def has_repo_name_or_error(show_error)
      @repo_name_exists = !(defined?(@repo_name)).nil?
      if !@repo_name_exists
        puts 'Error: repo name missing (-n your_name_here)'.c(91) if show_error
        @error = true
      end
    end
    
    #----------------------------------------------------------------------
    # main methods
    def run(commands)
      if @debug
        commands.each { |x| puts(x) }
      else
        commands.each { |x| system(x) }
      end
    end
    
    def set_globals
    
      puts_title 'Parameters'
    
      @git_bitbucket_origin =   "git@bitbucket.org:#{@org}/#{@repo_name}.git"
      @git_github_origin = "git@github.com:#{@org}/#{@repo_name}.git"
    
      puts 'debug: ' + @debug.to_s.c(93)
      puts 'working in: ' + Dir.pwd.c(93)
      puts 'create: ' + @create.to_s.c(93)
      puts 'migrate: ' + @migrate.to_s.c(93)
      puts 'add: ' + @add.to_s.c(93)
      puts 'language: ' + @language.to_s.c(93)
      puts 'repo name: '+ @repo_name.to_s.c(93)
      puts 'bitbucket: ' + @git_bitbucket_origin.to_s.c(93)
      puts 'github: ' + @git_github_origin.to_s.c(93)
      puts 'team_id: ' + @team_id.to_s.c(93)
      puts 'org: ' + @org.to_s.c(93)
    end
    
    def create_repo
      puts_title 'Creating'
    
      #error checks
      has_repo_name_or_error(true)
      goodbye if @error
    
      puts @sep
    
      commands = [
          gitter_create(@repo_name)
      ]
    
      run commands
    end
    
    
    def add_repo
      puts_title 'Adding repo to team'
    
      #error checks
      has_repo_name_or_error(true)
      goodbye if @error
    
      puts @sep
    
      commands = [
          gitter_add(@repo_name)
      ]
    
      run commands
    end
    
    def migrate_repo
    
      puts_title "Migrating Repo to #{@repo_provider}"
    
      #error checks
      has_repo_name_or_error(true)
      goodbye if @error
    
      if Dir.exists?("#{@repo_name}.git")
        puts "#{@repo_name} already exists... recursively deleting."
        FileUtils.rm_r("#{@repo_name}.git")
      end
    
      path = "#{@repo_name}.git"
      commands = [
        git_clone_mirror(@git_bitbucket_origin, path),
        git_list_origin(path),
        git_push_mirror(@git_github_origin, path)
      ]
    
      run commands
    end
    
    #----------------------------------------------------------------------
    #sequence control
    hello
    get_options
    
    #do stuff
    set_globals
    create_repo if @create
    migrate_repo if @migrate
    add_repo if @add
    
    #peace out
    goodbye
    

    Then, to use the script:

    # create a list of repos
    foo
    bar
    baz
    
    # execute the script, iterating over your list
    while read p; do ./bitbucket-to-github.rb -a -n $p; done

提交回复
热议问题