本記事ではリポジトリマージの手順について載せていきます。
また、「GitHub.com」でForkを利用した場合のリポジトリ間マージについても触れていきます。
以下、目次です。
リポジトリ間のマージ
前提条件とパターン
リポジトリの前提条件は次の通りです。
- リポジトリA(オリジナル)
- リポジトリB(複製)
今回は、次のパターンを想定しています。
- B ← A(BにAの内容をマージする)
- A ← B(AにBの内容をマージする)
※リポジトリBは次のいずれかの手順で作成可能です。
- リポジトリAをFork(GitHub利用)
- リポジトリAをClone後に新規リポジトリBとして登録
コマンドで試します
リポジトリ間マージ:B ← A
- リポジトリBはクローンしておきます。
- リポジトリAは何かしら変更しておきます。
→ リポジトリAの変更を取り込んでいきましょう。
# リポジトリBに移動
cd repoB
# 取込元にAを追加して確認
git remote add upstream https://github.com/xxxx/RepoA.git
git remote -v
# 取込実施&マージ
git fetch upstream
git merge upstream/main
# リポジトリB(リモート)に反映
git push
※マージの際にコンフリクトがある場合は通常のブランチ間マージのように対応が必要です。
リポジトリ間マージ:A ← B
方向を逆にするだけで同じように実施出来ます。
- リポジトリAはクローンしておきます。
- リポジトリBは何かしら変更しておきます。
# リポジトリAに移動
cd repoA
# 取込元にBを追加して確認
git remote add downstream https://github.com/xxxx/RepoB.git
git remote -v
# 取込実施&マージ
git fetch downstream
git merge downstream/main
# リポジトリA(リモート)に反映
git push
GitHub.com上の場合
続いて、GitHub.com上だけでリポジトリ間のマージについて調べます。
リポジトリの前提条件は次の通りです。
- リポジトリA
- リポジトリB(リポジトリAをFork)
GitHubの場合:B ← A
次の画像はForkしたリポジトリです。
それぞれのリポジトリで変更した状態ですが、Forkしたリポジトリでは「ahead」「behind」「Sync fork」といった項目があります。
- ahead:fork先(下流)の変更量
- behind:fork元(上流)の変更量
- Sync fork:上流→下流に同期
Sync forkで上流の変更を取り込む場合、次のような画面になります。
↑の場合は、Fork先で特に変更もないので単純に取込が出来ます。
続いての場合、Fork先で変更があって自動的にマージ出来ない場合は「Sync fork」において「Discard」という選択しか取れません。
この選択の場合、fork先の変更を破棄(内部的にはgit reset –hard)が行われ、上流の取り込みが行われます。
廃棄したくない・・・。
pull requestの選択肢が残されているよ。
xx commits aheadだったり、xx commits behindをクリックすると、リポジトリ間のpull requestになって、反映作業を進めることが出来ます。
ところでDiscardを選択した場合、Fork先での変更は簡単に破棄出来てしまいます(Write以上の権限)。現状の仕様なのか不具合なのかわかりませんが、ブランチ保護ルールで強制push(push -f)を禁止していても、破棄出来てしまいます。うっかり操作して破棄ってなったら、リモート側なので復旧が大変そうです。
GitHubの場合:A ← B
上流に対する変更は「pull request」を経由した反映となります(あくまでGitHub.com上の操作だけに限定した場合です)。
xx commits aheadだったり、xx commits behindをクリックすると、リポジトリ間のpull requestになります。この先は通常のブランチ間のpull request操作と同等です。
GitHubの場合のまとめ
GitHub.com上だけの操作において、リポジトリ間マージの選択肢は次の通りです。
パターン | 手順 |
---|---|
B ← A (自動マージ可) | Sync fork or pull request |
B ← A (自動マージ不可) | pull request |
A ← B | pull request |
(参考) GitHubで新規リポジトリ作成(複製登録)
手元にローカルリポジトリがある状態で「git push」をしようとした場合、上手くいきません。例えば、git clone → remote url変更 → push という操作です。
remote: Repository not found.
fatal: repository 'https://github.com/xxxx/xxxx.git/' not found
GitHubのForkを使わないでリモートリポジトリを複製したいのよ。
権限(アクセストークン)を持っていてもこのようなエラーになります。sshならば解決出来るという記事を見たことがありますが、私はhttpsで実施したいのです。
解決方法は次の通りです。
- GitHubでリポジトリ登録
→ コンテンツ何も無しの未履歴で登録します。 - ローカルリポジトリの「remote set-url」を変更
→ git remote set-url –push origin <repository url> - git push
最初にGitHubで枠を作らないとだめなようです。
(参考) ForkとCloneの違い
念のため、Cloneとの違いを書きます。
Fork | Clone | |
---|---|---|
操作 | ・リポジトリを自分のアカウントやOrganizationにコピー。 | ・既存のリポジトリをローカルマシンにコピー。 |
目的 | ・コントリビューションのための開発。 | ・自分自身の開発や変更。 |
メリット | ・オリジナルのリポジトリを変更せずに独自の変更を加えられる。 ・自分自身のアカウントで管理できる。 | ・リポジトリ全体をダウンロードして開発や変更ができる。 |
デメリット | ・オリジナルのリポジトリが更新された場合、手動で変更を取り込む必要がある。 ・自分自身のリポジトリのメンテナンスが必要。 | ・オリジナルのリポジトリへの変更を行えない(PullRequest&Pushすれば可)。 ・ローカルマシンのストレージを占有する可能性がある。 |
少々、雑な部分はありますが、主な違いはこの通りでしょうか。
なお、元々のリポジトリをベースにするが、切り離して新しく開発したいのであれば、Forkではなく、Clone → 新規リポジトリ登録という流れが自然です(必要に応じて登録前に履歴を圧縮することもある)。
まとめ
本記事ではリポジトリ間のマージについてご紹介しました。
- コマンドを使う場合、remoteのurlを追加することでマージが可能です。
- GitHubでForkを使う場合、Sync forkやリポジトリ間のpull request発行によってマージが可能です。
最後までご覧いただきありがとうございました。
コメント