もっぺんプログラミング(´・ω・`)

もっぺん頑張って副業プログラマを目指してます。

Gitでローカルリポジトリを後からリモート管理にする方法

すごく初歩的な課題なのですが、ローカルでGit管理した後に、GitHubやBitBucket管理に移行する方法がが分からなかったので調べてみました。

この記事のゴール

ローカルのGitリポジトリを、新規作成したBitBucketのリポジトリにPUSHする!

背景

Gitを使う場面でよく見かけるのが、GitHubなどからCloneして使う方法ですよね。

存在するリポジトリをローカルに持ってきて使うのはその通りなのですが、自分で作ったソフトウェアをGit管理するには、どうしたらいいんだろう?と思ったのがきっかけです。

  • ソフトウェアを開発するときは、先にGitHub上で空のリポジトリを作って、Cloneするところから始めないとダメ?
  • ローカルでコードを書き始めてから、GitHub管理に移行するには、上記のように改めてCloneして、そこにファイルを手で移動しないとダメ?

そんな不便なはずなし!

やってみる

ローカルリポジトリを作成

ここでは、BitBucketでソースコード管理することを前提に作業を進めます。

まずは、ローカルでGit管理開始

> dev % 
> dev % mkdir hello
> dev % cd hello
> hello % echo "print('hello!');" > hello.py 
> hello % python hello.py                   
hello!

とりあえず、ディレクトリ作ってHelloだけ表示するPythonプログラム作成

> hello % git init
Initialized empty Git repository in /Users/momoizo/Documents/dev/hello/.git/

git init コマンドで、ローカルリポジトリ作成!
先程作った、hello.py をリポジトリに追加します。
git status で状態を見つつ、add からの commit !

> hello % git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    hello.py

nothing added to commit but untracked files present (use "git add" to track)
> hello % git add .  
> hello % git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file:   hello.py

> hello % git commit -m "first commit"
[master (root-commit) 93e51ea] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 hello.py
> hello %                     

これで、ローカルリポジトリが作成できました。

次に、このリポジトリをBitBucketにアップしてみます。

BitBucketにリポジトリ作成

BitBucketは、Atlassian社が提供するオンラインのGitリポジトリです。
オンラインのGitリポジトリといえば、GitHubが有名ですが、BitBucketは、他にもドキュメント管理や、タスク管理などの機能も無料で使えるなどの特徴があります。
GitHubも、いろんな機能を持っていますが)

今後、開発でそれらの機能も使ってみたいので、今回はBitBucketで作業を進めます。

BitBucketで新規リポジトリ作成
BitBucketで新規リポジトリ作成

Create Repositoryで先に進むと、次のような画面が出ます。

リポジトリ新規作成画面
リポジトリ新規作成画面

ここでポイントになるのは、「Readmeを含めますか?」です。

「No」を選んだ場合、空のリポジトリが作成され、ローカルリポジトリのPUSHも非常に簡単なのです。
でも、せっかくなので、初期ReadMeを自動生成して欲しい気も。

以降は、それぞれのパターンでPUSHの仕方を記載します。

ローカルリポジトリをPUSH(1):ReadMeを含めなかった場合

実は、空の状態でリポジトリを作ると、BitBucketの画面でローカルリポジトリをPUSHするためのコマンドを教えてくれます!

空のリポジトリに何か入れよう
空のリポジトリに何か入れよう

試しに、このコマンドを実行してみましょう。

> hello % git remote add origin https://momoizo@bitbucket.org/momoizo/hello_python.git

> hello % git push -u origin master

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 233 bytes | 233.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://bitbucket.org/momoizo/hello_python.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
> hello % 

できた!簡単でしたね!
※初めて接続する場合、BitBucketの認証を求められるかもしれません。

ローカルリポジトリをPUSH(2):ReadMeを含めた場合

次に、ReadMeを含めたリポジトリを作った場合です。
この場合、画面に案内されるのは、「clone して使ってね」という操作のみです。

ReadMeを含めてリポジトリを作った場合
ReadMeを含めてリポジトリを作った場合

試しに、リモートリポジトリに接続してPUSHしてみます。

リモートリポジトリに接続

既存のリモートリポジトリがある場合は削除して、改めて追加しなおします。

> hello % git remote
origin
> hello % git remote rm origin
> hello % git remote add origin https://momoizo@bitbucket.org/momoizo/hello_python.git
> hello % git remote -v
origin  https://momoizo@bitbucket.org/momoizo/hello_python.git (fetch)
origin  https://momoizo@bitbucket.org/momoizo/hello_python.git (push)
> hello % 

そのままPUSH

git push コマンドでリモートリポジトリにPUSHします。 git push origin master は、originというリモートリポジトリの、master ブランチにソースコードをPUSHするという意味です。

> hello % git push origin master
To https://bitbucket.org/momoizo/hello_python.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://momoizo@bitbucket.org/momoizo/hello_python.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
> hello % 

失敗!リジェクト(拒否)されてしまいました…

ヒントを見ていると、push の前に pull して。と言っているようです。
リモートリポジトリには、ローカルにはない「ReadMeの追加」という操作が入っているので、先にその修正を取り込まないといけない(Pullしないといけない)のですね。

リモートリポジトリの内容をPULLする

指摘にしたがって、PULLしてみましょう。

> hello % git pull origin master
warning: no common commits
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://bitbucket.org/momoizo/hello_python
 * branch            master     -> FETCH_HEAD
 * [new branch]      master     -> origin/master
fatal: refusing to merge unrelated histories
> hello % 

失敗!! 「unrelated histories」つまり、編集履歴の関連が無いのでマージ(統合)できない。ということのようです。

確かに、それぞれ別々に編集してきたので、統合が難しいのかもしれません。
ただ今回は、同じ名前のファイルが無いため(リモートは、ReadMe.mdのみ)強引にマージしても問題は起こりません。

では、やってみましょう。

mergeのオプションに「--allow-unrelated-histories」をつけることで、強制的にマージさせることが出来ます。

先程のpull コマンドの結果を見ると、リモートリポジトリの内容はローカルの「origin/master」という 新しいブランチに持ってきていることがわかります。
(実は、pull コマンドは、fetch (リモートからローカルに持ってくる)操作と、merge (統合)操作を同時に行うコマンドなのです。)

ですから、後はブランチから、ローカルの master にマージできればOKです。
merge コマンドを使いましょう。

> hello % git merge --allow-unrelated-histories origin/master -m "remote merge"
Merge made by the 'recursive' strategy.
 README.md | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)
 create mode 100644 README.md
> hello % 

README.mdが追加されました!

あとは、これをリモートにPUSHすれば…

> hello % git push origin master
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 498 bytes | 498.00 KiB/s, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://bitbucket.org/momoizo/hello_python.git
   aea44a4..2f1675d  master -> master
> hello % 

できました!
BitBucketを確認してみたところ、ソースに hello.py が追加されています。

リモートにPUSH出来ました
リモートにPUSH出来ました

大成功!

まとめ

リモートリポジトリが空なら(履歴が無いなら)、そのままローカルリポジトリのソースをPUSHすることが出来ました。
仮に、リモートリポジトリに中身があっても、うまくローカルリポジトリにマージすれば、PUSHすることが出来ました。

コマンド操作なので、Gitに慣れていないと混乱するかもしれませんが、簡単なケースで色々試してみてください!

それでは!

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

わかばちゃんと学ぶ Git使い方入門〈GitHub、Bitbucket、SourceTree〉

  • 作者:湊川 あい
  • 発売日: 2017/04/21
  • メディア: 単行本(ソフトカバー)