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

前端 未结 11 1764
孤城傲影
孤城傲影 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 03:59

    You can refer to the GitHub page "Duplicating a repository"

    It uses:

    • git clone --mirror: to clone every references (commits, tags, branches)
    • git push --mirror: to push everything

    That would give:

    git clone --mirror https://bitbucket.org/exampleuser/repository-to-mirror.git
    # Make a bare mirrored clone of the repository
    
    cd repository-to-mirror.git
    git remote set-url --push origin https://github.com/exampleuser/mirrored
    # Set the push location to your mirror
    
    git push --mirror
    

    As Noted in the comments by L S:

    • it is easier to use the Import Code feature from GitHub described by MarMass.
      See https://github.com/new/import
    • Unless... your repo includes a large file: the problem is, the import tool will fail without a clear error message. Only GitHub Support would be able to diagnose what happened.
    0 讨论(0)
  • 2020-12-02 03:59

    I made the following bash script in order to clone ALL of my Bitbucket (user) repositories to GitHub as private repositories.


    Requirements:

    • jq (command-line JSON processor) | MacOS: brew install jq

    Steps:

    1. Go to https://github.com/settings/tokens and create an access token. We only need the "repo" scope.

    2. Save the move_me.sh script in a working folder and edit the file as needed.

    3. Don't forget to CHMOD 755

    4. Run! ./move_me.sh

    5. Enjoy the time you have saved.


    Notes:

    • It will clone the BitBucket repositories inside the directory the script resides (your working directory.)

    • This script does not delete your BitBucket repositories.


    Need to move to public repositories on GitHub?

    Find and change the "private": true to "private": false below.

    Moving an organization's repositories?

    Checkout the developer guide, it's a couple of edits away.


    Happy moving.

    #!/bin/bash
    
    BB_USERNAME=your_bitbucket_username 
    BB_PASSWORD=your_bitbucket_password
    
    GH_USERNAME=your_github_username
    GH_ACCESS_TOKEN=your_github_access_token
    
    ###########################
    
    pagelen=$(curl -s -u $BB_USERNAME:$BB_PASSWORD https://api.bitbucket.org/2.0/repositories/$BB_USERNAME | jq -r '.pagelen')
    
    echo "Total number of pages: $pagelen"
    
    hr () {
      printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -  
    }
    
    i=1
    
    while [ $i -le $pagelen ]
    do
      echo
      echo "* Processing Page: $i..."
      hr  
      pageval=$(curl -s -u $BB_USERNAME:$BB_PASSWORD https://api.bitbucket.org/2.0/repositories/$BB_USERNAME?page=$i)
      
      next=$(echo $pageval | jq -r '.next')
      slugs=($(echo $pageval | jq -r '.values[] | .slug'))
      repos=($(echo $pageval | jq -r '.values[] | .links.clone[1].href'))
      
      j=0
      for repo in ${repos[@]}
      do
        echo "$(($j + 1)) = ${repos[$j]}"
        slug=${slugs[$j]}
      git clone --bare $repo 
      cd "$slug.git"
      echo
      echo "* $repo cloned, now creating $slug on github..."  
      echo  
    
      read -r -d '' PAYLOAD <<EOP
      {
        "name": "$slug",
        "description": "$slug - moved from bitbucket",
        "homepage": "https://github.com/$slug",
        "private": true
      }
      EOP
    
      curl -H "Authorization: token $GH_ACCESS_TOKEN" --data "$PAYLOAD" \
          https://api.github.com/user/repos
      echo
      echo "* mirroring $repo to github..."  
      echo
      git push --mirror "git@github.com:$GH_USERNAME/$slug.git"
      j=$(( $j + 1 ))
      hr    
      cd ..
      done  
      i=$(( $i + 1 ))
    done
    
    0 讨论(0)
  • 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 <very-long-access-token>" https://api.github.com/orgs/<org-name>/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<repos
    
    # good nuff
    
    0 讨论(0)
  • 2020-12-02 04:04

    There is the Importing a repository with GitHub Importer

    If you have a project hosted on another version control system as Mercurial, you can automatically import it to GitHub using the GitHub Importer tool.

    1. In the upper-right corner of any page, click , and then click Import repository.
    2. Under "Your old repository's clone URL", type the URL of the project you want to import.
    3. Choose your user account or an organization to own the repository, then type a name for the repository on GitHub.
    4. Specify whether the new repository should be public or private.
      • Public repositories are visible to any user on GitHub, so you can benefit from GitHub's collaborative community.
      • Public or private repository radio buttonsPrivate repositories are only available to the repository owner, as well as any collaborators you choose to share with.
    5. Review the information you entered, then click Begin import.

    You'll receive an email when the repository has been completely imported.

    1. https://help.github.com/categories/importing-your-projects-to-github
    2. https://help.github.com/articles/importing-a-repository-with-github-importer/
    0 讨论(0)
  • 2020-12-02 04:07

    http://www.blackdogfoundry.com/blog/moving-repository-from-bitbucket-to-github/

    This helped me move from one git provider to another. At the end of it, all the commits were in the destination git. Simple and straight forward.

    git remote rename origin bitbucket
    git remote add origin https://github.com/edwardaux/Pipelines.git
    git push origin master
    

    Once I was happy that the push had been successful to GitHub, I could delete the old remote by issuing:

    git remote rm bitbucket
    
    0 讨论(0)
提交回复
热议问题