頭脳一式

人の記憶なんて曖昧なもの。すべての情報を頭に記憶するなんてナンセンス。困ったらここに来ればいいじゃん?というスタンスで最強のナレッジベースを目指すブログ

【GitLab】フォーク元のリポジトリに追加された新規ブランチを自分のリモートリポジトリに反映する。

今回は、次のような場合を考えます。

リポジトリ masterブランチ developブランチ develop2ブランチ
フォーク元
フォークしたリモートリポジトリ
(自分のリモートリポジトリ)
×
ローカルリポジトリ ×

上記のような感じです。
つまり、一度フォークした後に、フォーク元にdevelop2ブランチが作成されたとき、
これを自分のリモートリポジトリにも反映させたいなぁ。 というときの手順です。

1.ブランチの状態を確認する。

まずはブランチの状態を確認するため以下のコマンドを実行します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git branch -a
* develop
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master

実行結果を見るとローカル側とリモート側にdevelopブランチ、masterブランチがあることが確認できました。
ちなみにこの場合のoriginとは以下のとおりフォークしたリポジトリを指します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git remote -v
origin  http://localhost:8888/user01/prj3.git (fetch)
origin  http://localhost:8888/user01/prj3.git (push)

つまり、git branch -aの結果ではdevelop2ブランチの存在を確認できない状態になっています。
なぜかというと、フォークしたリモートリポジトリにもdevelop2ブランチが存在しないためです。

2.フォーク元のリポジトリをローカルへ追加する。

カレントディレクトリとフォーク元のリポジトリを関連付けるには以下のコマンドを実行します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git remote add fork_moto http://localhost:8888/group1/prj3.git

実行したコマンドの形式は次のとおりです。
git remote add ブランチ名 フォーク元ブランチのURL
上のコマンドを実行したらgit remoteで再度確認します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git remote -v
fork_moto       http://localhost:8888/group1/prj3.git (fetch)
fork_moto       http://localhost:8888/group1/prj3.git (push)
origin  http://localhost:8888/user01/prj3.git (fetch)
origin  http://localhost:8888/user01/prj3.git (push)

これでフォーク元のリポジトリを追加することが出来ました。
次に、フォーク元リポジトリの履歴情報を取得します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git fetch fork_moto
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From http://localhost:8888/group1/prj3
 * [new branch]      develop    -> fork_moto/develop
 * [new branch]      develop2   -> fork_moto/develop2
 * [new branch]      master     -> fork_moto/master

これで以下のとおりフォーク元のブランチが確認できようになりました。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git branch -a
* develop
  master
  remotes/fork_moto/develop
  remotes/fork_moto/develop2
  remotes/fork_moto/master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master

3.フォーク元のリポジトリをローカルリポジトリのブランチとして反映する。

以下のコマンドでフォーク元のdevelop2ブランチをローカルリポジトリ内で作成します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (develop)
$ git checkout -b moto_develop2 fork_moto/develop2
Switched to a new branch 'moto_develop2'
Branch 'moto_develop2' set up to track remote branch 'develop2' from 'fork_moto'.

実行したコマンドの形式は次のとおりです。
git checkout -b ローカルブランチ名 フォーク元リポジトリ名/フォーク元ブランチ名

次のコマンドで作成されたかを確認します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (moto_develop2)
$ git branch -a
  develop
  master
* moto_develop2
  remotes/fork_moto/develop
  remotes/fork_moto/develop2
  remotes/fork_moto/master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master

はい、これで作成されました。

4.自分のリモートリポジトリへ反映する。

手順1~3で自分のリモートリポジトリには存在せず、フォーク元のみに存在したブランチをローカルへ持ってくることに成功しました。 表でいうと以下のとおりです。

リポジトリ masterブランチ developブランチ develop2ブランチ
フォーク元
フォークしたリモートリポジトリ
(自分のリモートリポジトリ)
×
ローカルリポジトリ

後はこれを自分のリモートリポジトリに反映するだけです。

shoya@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj3 (moto_develop2)
$ git push origin moto_develop2
Counting objects: 3, done.
Writing objects: 100% (3/3), 270 bytes | 270.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for moto_develop2, visit:
remote:   http://localhost/user01/prj3/merge_requests/new?merge_request%5Bsource_branch%5D=moto_develop2
remote:
To http://localhost:8888/user01/prj3.git
 * [new branch]      moto_develop2 -> moto_develop2

これで完了です。

【GitLab】気づいたこと・分かったこと

触ってて気づいたこと・分かったことをまとめます。

チェックアウトするとファイルのタイムスタンプが、チェックアウトした日時に変わる。

なんでチェックアウトする度にタイムスタンプが変わるんだろう…って思ってたけど分かった気がする。
git checkout [branch]ってブランチを切り替える作業のことだけど、これってつまり「リポジトリから対象のブランチのファイルを取り出して上書きする」ってことだからタイムスタンプが変わるんだ!と気づいた。

リモートリポジトリに複数のブランチが在っても、クローン時はmasterブランチしか作成されない

例えば、以下のようにリモートリポジトリにはmasterブランチとdevelopブランチが在るけど、まだローカルリポジトリが無い場合。

リポジトリ masterブランチ developブランチ
リモートリポジトリ
ローカルリポジトリ × ×

この状態でgit cloneしてもmasterブランチしか取り込まれない。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2
$ git clone http://localhost:8888/group1/prj1.git
Cloning into 'prj1'...
remote: Enumerating objects: 34, done.
remote: Counting objects: 100% (34/34), done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 34 (delta 3), reused 0 (delta 0)
Unpacking objects: 100% (34/34), done.

↑クローン完了。
↓ブランチの一覧を表示してみる。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj1 (master)
$ cd prj1/
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master

実行結果を確認するとローカル側はmasterブランチしかない。
けどリモート側にはdevelopブランチが在ることが確認できる。
つまりリモートのリポジトリ情報(履歴情報)は取得できているわけだ。
なのでdevelopブランチが欲しければ以下のコマンドを実行すれば良い。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj1 (master)
$ git checkout -b develop origin/develop
Switched to a new branch 'develop'
Branch 'develop' set up to track remote branch 'develop' from 'origin'.

↑developブランチの作成完了。
↓ブランチの一覧とlsの結果を見てみる。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj1 (develop)
$ git branch -a
* develop
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master
XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj1 (develop)
$ ls
20181231.md  README.md

ふむ。問題なさそうだ。

チェックアウト時にuse "git push" to publish your local commitsというメッセージが表示される場合

ローカルブランチをチェックアウトしたとき、たまに以下のようにuse "git push" to publish your local commitsと表示されることがある。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace2/prj1 (master)
$ git checkout develop
Switched to branch 'develop'
Your branch is ahead of 'origin/develop' by 1 commit.
  (use "git push" to publish your local commits)

これはリモートリポジトリの追跡ブランチに対してローカルリポジトリのブランチがコミットされている場合に表示されるメッセージで、
この場合、ローカルリポジトリのブランチは、リモートリポジトリの追跡ブランチよりも一歩先を行っていることを指します。
この状態であればgit pushを行ってもコンフリクトが発生することはありません。
但しこのメッセージはgit fetchしている前提。git fetchしていない場合はローカルリポジトリのブランチの方に変更があってもこのメッセージは表示されない。

【GitLab】リモートリポジトリに追加された新規ブランチをローカルリポジトリへ取り込むときの手順ver2

この記事ではリモートリポジトリのブランチを基に、直接ローカルリポジトリへ取り込む手順をまとめます。

リポジトリ masterブランチ develop6ブランチ
リモートリポジトリ
ローカルリポジトリ ×

つまり、リモートリポジトリ上に在るdevelop6ブランチをローカルリポジトリへ取り込むための手順になります。

1.リモートリポジトリの最新情報(履歴)をローカルリポジトリへ反映する。

何はともあれgit fetch

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git fetch
warning: redirecting to http://localhost:8888/user01/prj2.git/
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From http://localhost:8888/user01/prj2
 * [new branch]      develop6   -> origin/develop6

これで最新化されました。

2.リモートリポジトリのブランチを確認する。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (develop6)
$ git branch -r
  fork/fork1
  origin/HEAD -> origin/master
  origin/develop
  origin/develop2
  origin/develop3
  origin/develop4
  origin/develop5
  origin/develop6
  origin/master

先ほどgit fetchしたのでdevelop6ブランチが一覧上で確認できました。

3.リモートリポジトリにあるdevelop6ブランチをローカルリポジトリへ取り込む。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git checkout -b develop6 origin/develop6
Switched to a new branch 'develop6'
Branch 'develop6' set up to track remote branch 'develop6' from 'origin'.

これでローカルリポジトリへの取り込みが完了しました。

ちなみにgit fetchせずにcheckoutしようとした場合

以下のエラーが出てcheckoutできませんでした。やはりgit fetchは必要なようです。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git checkout -b develop6 origin/develop6
fatal: 'origin/develop6' is not a commit and a branch 'develop6' cannot be created from it

以上。

【GitLab】よく使うGitコマンド&用語の意味

主に、Git for WindowsなどのCUIで使用するGitコマンドをまとめます。

git init

git initは、指定したディレクトリにリポジトリ機能を持たせることが出来るコマンド。
このコマンドを実行しないとコミットしたりできない。但し、リモートブランチを取得する場合はこのコマンドは不要。

カレントディレクトリにリポジトリ機能を持たせる

git init

指定したディレクトリにリポジトリ機能を持たせる

git init dir

Blame

Blameは、指定したファイルに対して、行ごとに誰がいつコミットしたのかを表示する機能。

git tag

git tagは特定のコミットに対して名前を付けるコマンド。
このtagはリポジトリ内で一意の命名にしなければならず、コミットIDやブランチ名の代わりとして使用できる。
通常、コミットを行うとコミットIDが生成されるが、後から見返したときにそのコミットIDの意味を見失いやすい。
使いどころとしては例えば1つのjsファイルの中で5つのメソッドを作成しなければならない場合、
メソッドが1つ完成するごとにtag付けを行うことで、後から見返したときにその時点のコミットがどんなものなのか思い出しやすくなるといった使い方ができる。

git branch

ブランチというはの一般的に"分岐"とか"枝"と言われます。
例えば本番運用中のサービスに機能Aを追加したい、機能Bを追加したい、バグを修正したいといった要望があると思います。 こういうときは要望ごとにブランチを作ります。
通常、本番運用中の資源はmasterブランチに格納されているので、masterブランチを起点として機能A用のブランチ(master + A)、機能B用のブランチ(master + B)、バグ修正用のブランチ(master + bug)を作ることによってそれぞれを独立した形で並行して開発作業を行うことができます。
この方法で開発作業を進めれば、機能Aと機能Bの資源がごちゃまぜになったりすることを防いだり、「機能Bだけ先行してリリースしたい」といったときに機能B用のブランチだけmasterとマージすることにより、他のブランチに影響せずスムーズにリリースすることができます。

新規ブランチを作成する

コマンド 意味
git branch [new branch] ローカルリポジトリ上に [new branch]の名前で新規ブランチを作成します。作成する際は今現在いるブランチを起点として新規ブランチを作成します。

ブランチの一覧を表示する

コマンド 意味
git branch ローカルリポジトリのブランチを一覧表示します。
git branch -r リモートリポジトリのブランチを一覧表示します。
git branch -a ローカルリポジトリと、リモートリポジトリのブランチを一覧表示します。
git branch -vv ローカルリポジトリのブランチが、リモートリポジトリのどのブランチを追跡しているか確認できます。

git checkout

このコマンドで私が良く使うのは以下の機能です。

  • 新規ブランチを作成してチェックアウト。
  • 既存ブランチへチェックアウト。

※チェックアウトとは、ブランチを切り替えることを指します。

ブランチの一覧を表示する

コマンド 意味
git checkout -b [new branch] 新規ブランチを作成し、チェックアウトします。
git checkout [branch] 既存ブランチへチェックアウトします。
# git checkout -b [new branch]
git checkout -b develop

git clone

リモートリポジトリの内容をローカルへ複製します。

# git clone [リポジトリURL]
git clone http://localhost/group1/prj1.git

git remote

ローカルリポジトリに登録されているリモートリポジトリの一覧を表示します。

$ git remote -v
origin  http://localhost/group1/prj1.git (fetch)
origin  http://localhost/group1/prj1.git (push)

originとは、リモートリポジトリ(URL)の別名を指します。
コマンド操作をする際にいちいちURLを引数に取ると長くなってしまうので、
コマンド操作をするときはこの別名を使用します。
SQLでいうAS句で指定する別名みたいなものです。

git merge

ブランチ同士のマージ(統合)をします。
例)
マージ元:developブランチ
マージ先:masterブランチ
つまり、developブランチの内容とmasterブランチへ統合します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj1 (master) //…①
$ git checkout develop
Switched to branch 'develop'

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj1 (develop) //…②
$ cat README.md
# prj1_develop2

abc

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj1 (develop) //…③
$ git checkout master
Switched to branch 'master'

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj1 (master) //…④
$ cat README.md
# prj_master1

abc

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj1 (develop) //…⑤
$ git checkout master
Switched to branch 'master'

git push

ローカルリポジトリの内容(変更)をリモートリポジトリに反映する操作。

git pull

リモートリポジトリの内容(変更)をローカルリポジトリへ反映する操作。
git fetch + git mergeから成る。

【GitLab】リモートリポジトリに追加された新規ブランチをローカルリポジトリへ取り込むときの手順ver1

この記事では次のようなケースを想定した手順をまとめました。

リポジトリ masterブランチ developブランチ
リモートリポジトリ
ローカルリポジトリ ×

つまり、リモートリポジトリにはdevelopブランチがあるのに、ローカルリポジトリにはない。
なのでローカルリポジトリへdevelopブランチを取り込みたいけど、どうすれば良いんだろう…
を解決するための手順です。

1.ローカルリポジトリのブランチを確認する。

まずは、ローカルリポジトリにどんなブランチが在るのかを確認するために以下のコマンドを実行します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git branch
* master

実行結果をみると、現時点ではローカルリポジトリにはmasterブランチしか存在していません。

2.リモートリポジトリのブランチを確認する。

次に、リモートリポジトリにどんなブランチが在るのかを確認するために以下のコマンドを実行します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git branch -r
  origin/HEAD -> origin/master
  origin/master

現時点では、リモートリポジトリも、masterブランチしか存在していません。
実際にはリモートリポジトリにdevelopブランチが存在しているのに、一覧には出て来ないのです。
なぜかというと、リモートリポジトリの最新情報(履歴)をローカルリポジトリへ反映していないからです。
この問題はgit fetchすると解消します。

3.リモートリポジトリの最新情報(履歴)をローカルリポジトリへ反映する。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (develop)
$ git fetch
warning: redirecting to http://localhost:8888/user01/prj2.git/
From http://localhost:8888/user01/prj2
 * [new branch]      develop   -> origin/develop

これでdevelopブランチの情報をローカルリポジトリへ反映させることができました。

4.再度、リモートリポジトリのブランチを確認する。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git branch -r
  origin/HEAD -> origin/master
  origin/develop
  origin/master

今度はちゃんと、developブランチが在ることを確認できました。

5.originがどこを指しているのかを確認する。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git remote -v
origin  http://localhost:8888/user01/prj2 (fetch)
origin  http://localhost:8888/user01/prj2 (push)

6.ローカルリポジトリにdevelopブランチを作成する。

今回は、リモートリポジトリにあるdevelopブランチをローカルリポジトリへ取り込みたいので、
ローカルリポジトリにもdevelopブランチを作成します。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (master)
$ git checkout -b develop
Switched to a new branch 'develop'

7.リモートリポジトリにあるdevelopブランチをローカルリポジトリへ取り込む。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj2 (develop)
$ git pull origin develop
warning: redirecting to http://localhost:8888/user01/prj2.git/
From http://localhost:8888/user01/prj2
 * branch            develop   -> FETCH_HEAD
Updating 5ba484a..39c4e0d
Fast-forward
 README.md | 1 +
 1 file changed, 1 insertion(+)

これでdevelopブランチをローカルリポジトリへ取り込むことが出来ました。
以上。

【GitLab】git pushできないときの対処方法。[You are not allowed to push code to protected branches on this project.]が発生する。

git push時に以下のエラーが発生する場合の対処方法。

XXXXX@DESKTOP-AQBVPOG MINGW64 /c/workspace/prj1 (master)
$ git push -u origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 285 bytes | 285.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: GitLab: You are not allowed to push code to protected branches on this project.
To http://localhost:8888/group1/prj1.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'http://localhost:8888/group1/prj1.git'

このエラーが出たとき、私はGitLabのdeveloperユーザでmasterブランチへpushしようとしていました。
とりあえずGoogle翻訳にかけてみたところ、次のとおり翻訳されました。

あなたがこのプロジェクトに保護されたブランチにコードをプッシュすることはできません。

そして気づきました。developerユーザの場合、masterブランチへpush出来ないことを。
次の画像を見ると、masterブランチがprotectedになっていることを確認できました。

masterブランチがprotectedになっている画像
masterブランチがprotectedになっているとdeveloperユーザでは`git push`できない。
つまり、developerユーザの場合、ローカルリポジトリで修正したmasterブランチのファイルをgit pushすることは出来ないのです。

【GitLab】git cloneできないときの対処方法。[Failed to connect to localhost port 80: Connection refused]が発生した場合

git cloneコマンド実行時の以下のエラーが発生する場合

$ git clone http://localhost/testgroup/javaprj.git
Cloning into 'javaprj'...
fatal: unable to access 'http://localhost/testgroup/javaprj.git/': Failed to connect to localhost port 80: Connection refused

私の環境ではポートフォワーディングしているため、GitLabがそのまま表示しているURLではcloneできませんでした。 以下のようにポートフォワーディングで設定しているポート番号を使用すると'git clone'がうまく通りました。

$ git clone http://localhost:8888/testgroup/javaprj.git
Cloning into 'javaprj'...
warning: You appear to have cloned an empty repository.