如何将所有分支的git存储库从bitbucket移动到github?


334

将所有分支和完整历史记录的git存储库从bitbucket移动到github的最佳方法是什么?是否有我必须使用的脚本或命令列表?


9
Github为此提供了工具和文档:help.github.com/articles/…help.github.com/articles/…–
mems

聚会晚了一点,但是这里有一个迁移脚本:gist.github.com/chinmaya-n/cff02f1277c811deab2e550f2aad9967
inblueswithu

Answers:


394

您可以参考GitHub页面“ 复制存储库

它用:

这将给:

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

如前所述在注释人民共同LS


2
这种方法给我带来了一个问题(不确定是否有问题)。当我将存储库从bitbucket镜像到github时,对于5个分支,它在github中显示为“ Compare and Pull Request”。它没有在github中显示为分支。我该怎么办?
Siddharth 2014年

2
那问题和维基呢?
Vladislav Rastrusny 2014年

@FractalizeR Wiki只是另一个仓库,您也可以复制它(github.com/blog/699-making-github-more-open-git-backed-wikis)。但是,没有简单的方法可以复制问题。您需要使用Api(各种GitHub存储库备份程序都这样做:addyosmani.com/blog/backing-up-a-github-account
VonC

3
如果您也想将存储库从Github移至Bitbucket,则此方法有效。
simeg 2016年

1
我需要使用此方法来复制存储库,因为它包含一个大文件(> 100MB)。GH不允许在其存储库中使用大文件。在将存储库推送到GH之前,我删除了大文件。但是,除其他问题外,使用GH的“ 导入存储库 ”功能在95%的时间内都是正确的选择,如另一个答案所述。但是,如果失败,它不会给出有用的错误消息,您必须联系GH支持。GH支持使我知道了文件大小限制。
LS

412

非常简单

在GitHub中创建一个新的空存储库(没有自述文件或licesne,您可以在以前添加它们),然后将显示以下屏幕

在内部导入代码选项,您可以粘贴位桶URL的repo和voilà!

点击导入代码


12
您实际上是在这里回答问题,因为接受的答案仅显示与Git相关的通用方法。您的答案更简单!
Emile Bergeron 2015年

6
只要您是创建存储库的人,这个答案就不错了。如果其他人为您创建了存储库(例如,负责分支创建的管理员),则此操作将无效。接受的答案是在这种情况下的解决方法。
Master.Aurora 2015年

4
前往考虑使用此方法的任何其他人,使用此服务之前,请在以前的存储库主机上删除两因素身份验证,否则,您将陷入尝试删除GitHub中新创建的存储库的无休止循环中,并且摆脱这种情况的唯一方法是/import将URL末尾的替换/settings为访问设置并将其删除。
戴夫

1
小警告-如果您遇到问题,则不会收到描述性错误消息。
罗伯特·希尔'16

95%的时间使用GH的“ 导入存储库 ”功能是正确的选择。但是,如果失败,它不会给出有用的错误消息,您必须联系GH支持。我无法将其用于一个存储库,因为它包含一个大文件(> 100MB)。我需要使用 可接受的CLI方法,仅在将存储库推送到GH之前删除大文件。
LS

125

如果您在github上找不到“导入代码”按钮,则可以:

  1. 直接打开 Github Importer并输入url。它看起来像:github importer的屏幕截图
  2. 给它起个名字(否则它将自动导入名称)
  3. 选择 PublicPrivate回购
  4. 请点击 Begin Import

更新: 最近,Github宣布了“ 导入带有大文件的存储库 ”的功能


不幸的是,这对我尝试从codebasehq转到git-hub无效,给出了“不支持此URL”。:(
sjmcdowall

@sjmcdowall抱歉,没有,但是我相信它应该可以正常工作,因为codebasehq URL指向git存储库。
比尼亚姆

URL不再存在。
编码容器

我刚刚检查的@CodedContainer,它可以工作。我什至刚刚更新了屏幕截图。
biniam

1
如果您尚未登录GitHub,则该网址只会返回404。如果您已登录,则将加载导入工具。
杰森·赫特

41

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

这帮助我从一个git提供程序转移到另一个。最后,所有提交都在目标git中。简单直接。

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

一旦对推送成功成功感到高兴,就可以通过发出以下命令删除旧的远程服务器:

git remote rm bitbucket

2
请在您的答案中包含链接的相关部分,因为它应该能够独立存在。
k0pernikus

我收到一条错误消息:“错误:无法将Som refs推送到' url.gi ”提示:更新被拒绝,因为远程包含您在本地没有的工作。这通常是由另一个存储库推送到相同的ref引起的。您可能需要先整合远程更改(例如pull ...),然后再再次进行推送。有关详细信息,请参阅git push --help中有关快进的注释
编码容器

1
这是唯一在2019/3/3仍然有效的答案:)
Wang-Zhao-Liu QM

13

我有一个反向用例,即从github导入现有存储库到bitbucket。

Bitbucket提供了导入工具。唯一必要的步骤是将URL添加到存储库。

看起来像:

bitbucket导入工具的屏幕截图


5

我意识到这是一个老问题。几个月前,当我尝试做同样的事情时,我发现了它,但给出的答案不知所措。他们似乎都处理通过点菜发出的命令或通过GitHub导入器一次从Bitbucket导入到GitHub一个存储库的问题。

我从一个名为gitter的GitHub项目中获取了代码,并对其进行了修改以满足我的需求。

您可以派出要点,或从此处获取代码:

#!/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

然后,使用脚本:

# 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

5

使用GitHub Importer导入存储库

如果您有一个作为Mercurial托管在另一个版本控制系统上的项目,则可以使用GitHub Importer工具将其自动导入到GitHub。

  1. 在任何页面的右上角,单击,然后单击导入存储库。
  2. 在“您的旧存储库的克隆URL”下,键入要导入的项目的URL。
  3. 选择您的用户帐户或拥有存储库的组织,然后在GitHub上输入存储库的名称。
  4. 指定新的存储库是公共的还是私有的。
    • 公共存储库对GitHub上的任何用户都是可见的,因此您可以从GitHub的协作社区中受益。
    • 公共或私有存储库单选按钮私有存储库仅对存储库所有者以及您选择与之共享的任何协作者可用。
  5. 查看您输入的信息,然后单击“开始导入”。

完全导入存储库后,您会收到一封电子邮件。

  1. https://help.github.com/categories/importing-your-projects-to-github
  2. https://help.github.com/articles/importing-a-repository-with-github-importer/

2

如果要将本地git存储库移至另一个上游,也可以执行以下操作:

获取当前的远程URL:

git remote get-url的起源

将会显示类似以下内容:https : //bitbucket.com/git/myrepo

设置新的远程存储库:

git remote set-url origin git@github.com:folder / myrepo.git

现在推送当前(开发)分支的内容:

git push --set-upstream起源开发

现在,您在新遥控器中具有分支的完整副本。

(可选)返回此本地文件夹的原始git-remote:

git remote set-url origin https://bitbucket.com/git/myrepo

提供的好处是,您现在可以从github的另一个文件夹中获取新的git-repository,以便您拥有两个都指向不同远程对象的本地文件夹,前一个(bitbucket)和新的都可用。


2

我制作了以下bash脚本,以将所有Bitbucket(用户)存储库克隆到GitHub作为私有存储库。


要求:

  • jq(命令行JSON处理器)| 苹果系统:brew install jq

脚步:

  1. 转到https://github.com/settings/tokens并创建访问令牌。我们只需要“回购”范围。

  2. move_me.sh脚本保存在工作文件夹中,然后根据需要编辑文件。

  3. 别忘了 CHMOD 755

  4. 跑! ./move_me.sh

  5. 享受您节省的时间。


笔记:

  • 它将在脚本所在的目录(您的工作目录)中克隆BitBucket存储库。

  • 该脚本不会删除您的BitBucket存储库。


是否需要移至GitHub上的公共存储库?

查找并将其更改"private": true"private": false以下内容。

移动组织的存储库?

签出开发人员指南,几处修改了。


愉快的移动。

#!/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

1
有趣的脚本,结合令牌。整齐。已投票。
VonC

@VonC谢谢!
19:39鸣叫

1

以下是移动私有Git存储库的步骤:

第1步:创建Github存储库

首先,在Github.com上创建一个新的私有存储库。保持存储库为空很重要,例如在创建存储库时不要选中选项使用README初始化此存储库。

步骤2:移动现有内容

接下来,我们需要使用Bitbucket存储库中的内容填充Github存储库:

  1. 从Bitbucket中检出现有存储库
    $ git clone https://USER@bitbucket.org/USER/PROJECT.git
  1. 将新的Github存储库添加为从Bitbucket中检出的存储库的上游远程站点:
    $ cd PROJECT
    $ git remote add upstream https://github.com:USER/PROJECT.git
  1. 将所有分支(下面:仅是主节点)和标签送到Github存储库:
    $ git push upstream master
    $ git push --tags upstream

步骤3:清理旧存储库

最后,我们需要确保开发人员不会因为同一项目有两个存储库而感到困惑。以下是删除Bitbucket存储库的方法:

  1. 仔细检查Github存储库是否包含所有内容

  2. 转到旧的Bitbucket存储库的Web界面

  3. 选择菜单选项设置>删除存储库

  4. 添加新Github存储库的URL作为重定向URL

这样,存储库就完全安置在Github的新家中了。让所有开发人员知道!


-1

最简单的方法:

git remote rename origin repo_bitbucket

git remote add origin https://github.com/abc/repo.git

git push origin master

成功推送到GitHub后,请运行以下命令删除旧的远程服务器:

git remote rm repo_bitbucket
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.