6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Github で fork したリポジトリの簡便な同期と運用

Last updated at Posted at 2021-05-08

オープンソース(本家)の Github リポジトリ(upstream)を fork し,upstream のアップデートを 自身の Github リポジトリ (origin)に手動で取得することで簡便に同期し,運用する方法の備忘録です.upstream の対象ブランチは master (永続ブランチ)とします.なお,本家へのプルリクエストは想定せず(してもよいですが),originmasterupstream の純粋なコピーを維持します.

upstreamの永続ブランチ master と originの永続ブランチ master および main を用意

実際の開発は master から分岐した main を永続ブランチとして Github-flow で管理し,main から分岐した feature ブランチ(名前は適宜変更)で開発・修正を行い,Github の プルリクエスト で main に マージ します.本家の master がアップデートされたら適当なタイミングで上記を実行します.

本家のリポジトリを fork しローカルに git clone

本家のリポジトリを自身の Github に fork し,それをローカルに git clone し,ローカルリポジトリのディレクトリに移動します.このとき git branch で確認し,master が現在のブランチであることを想定します.

git clone git@github.com:<user>/<repo>.git
cd <repo>

本家のリポジトリを upstream として登録

upstream として指定する URLgit@github.com:<user>/<repo>.git のような Clone するときの SSHのURLです.

git remote add upstream URL
git remote -v  # 確認

upstream を ローカルリポジトリに取得

fetch コマンドで upstream をローカルリポジトリに取得します.ローカルの作業ディレクトリ(ワークツリー)への反映は行われません(作業ディレクトリの変更なし).
fetch の引数についてはこちらが参考になります.

git fetch upstream master

これで upstream/master が new branch として追加されます.git branch -a で確認すると以下のようになっているでしょう.

* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/upstream/master

main ブランチを作成し,デフォルトブランチに設定

origin での永続ブランチとして,main ブランチを作成します.

git checkout -b main
git push origin main

この状態では origin (Github)のデフォルトブランチは master のままですので,main に変更します.
Github の当該リポジトリにおいて,メニュー右端の Settings をクリックします(左側のメニューのBranchesはクリックしません).Default branch に現れる master の右端にある両方向矢印 ⇄ をクリックするとボックスが現れます.その master プルダウンから main を選択し,update をクリックします.最後に確認が現れますので,それをクリックします.
この状態で git branch -a で確認すると,以下のように remotes/origin/HEADorigin/master を指したままであることが分かります.

* main
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/main
  remotes/origin/master
  remotes/upstream/master

そこで,以下を実行します.

git remote set-head origin main

すると,以下の通り origin/main を指すように変更されます.

* main
  master
  remotes/origin/HEAD -> origin/main
  remotes/origin/main
  remotes/origin/master
  remotes/upstream/master

以上で,最初の準備が完了です.

新たにローカルにクローンする

以上で作成した,main(デフォルト)とmasterブランチを含むリポジトリをスパコン等の新たなローカル環境にクローンするには以下のようにします.

git clone git@github.com:<user>/<repo>.git
cd <repo>
git branch -a  # 確認

これですべてのブランチ情報がローカルに取得されますが,デフォルトブランチのmainのみがローカルにcheckoutされます.masterを取得してローカルにcheckoutするのは以下の通りです.

git checkout master

upstreamの情報は取得されませんので,必要に応じて,upstream(URLとします)を追加します.

git remote add upstream URL
git remote -v  # 確認

注意: mainを取得した後に,masterブランチをローカルで作成すると(git checkout -b master),このmasterの内容はmainのコピーになります.そこにoriginのmasterをpullするのは不適切です.

日々の作業

mainブランチからfeatureブランチを作成し,その中で作業を行います.

git checkout -b feature
git branch # 確認

add,commitして作業が終わったら,origin(GitHubのリポジトリ)にプッシュします.あらたに,topicブランチが作成されます.

git push origin feature

GitHubのプルリクエスト(プルリク)で,featureをmainにマージします.マージが終わったら,featureブランチは削除して構いません.
ローカルのmainに戻って,origin(GitHub)からpullして変更を取り込みます.最後にfeatureブランチを削除します.

git checkout main
git pull origin main
git branch -d feature

日々の作業前の確認

featureブランチで作業中の場合,以下のようにmasterブランチへの切り替えができません.

$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
        ...
Please commit your changes or stash them before you switch branches.
Aborting

featureでコミットしておくか,またはスタッシュに隠しておく必要があります.まだ作業中であればスタッシュが標準選択でしょう.

git stash

後でfeatureに戻って来たら元に戻します.

git checkout feature
git stash pop

upstream を ローカル に マージ し,origin に プッシュ

現在のブランチを master にして,取得した upstream/master を ローカルの master に マージ します.次に,ローカルの masterorigin/master に プッシュ します.

git checkout master
git fetch upstream master  # 必要に応じて
git merge upstream/master  # スラッシュ"/"に注意
git push origin master

これで本家(upstream/master)と ローカルの master および origin/master の同期が完了です.

今後,同期を継続するには,本家がアップデートされる度に,同じように git fetch upstream でローカルリポジトリに upstream/master を取得し,mergepush の一連の作業を実行します.

さらに tag を同期

このままでは tag が同期されませんので,tag が存在する場合は以下を実行します.

git pull upstream master --tags
git push origin master --tags

master を main に マージ

更新された mastermain にマージし,プッシュします.main ブランチが存在しない初回は master ブランチにおいて,git checkout -b main により,master から 分岐した main ブランチを作成します.

git checkout main
git merge master
git push origin main

コンフリクトが発生する場合は,後述の通り対応します.また,初回git remote set-head origin main を実行し,リモートリポジトリ origin のデフォルトブランチ を main にしておきます.Github でもデフォルトブランチを main に変更する手続きが必要のようです.

更新された main ブランチを feature ブランチに マージ

feature ブランチで作業中に(コミットまたはスタッシュしておきます) upstream/master の更新を取得して main ブランチが更新された場合を想定し,その main ブランチを feature ブランチに マージ します.この作業が必要なのは main から feature へ分岐後に main が更新された場合です.main の更新がない場合は次の プルリクエスト で main へ マージ に飛びます.

git checkout feature
git merge main

ターミナルに CONFLICT (content): Merge conflict in coawst.bash のように CONFLICT で始まる行が現れたら,その行で示されたファイル中にコンフリクト(競合)の内容が書き込まれています.そのファイルをエディタで開き,適切に編集します.
以下のコンフリクト内容の例では <<<<<<< HEAD から ======= までが feature の,======= から >>>>>>> main までが main の内容となっており,両者に競合があることが分かります.

<<<<<<< HEAD
#export   NETCDF_CONFIG=/usr/bin/nc-config
=======
export   NETCDF_CONFIG=/usr/bin/nf-config
#export   NETCDF_CONFIG=/vortexfs1/apps/impistack-1.0/bin/nf-config
>>>>>>> main

これを例えば以下のように不要な行を削除する等,適切に編集します.この例では main を残しました.

export   NETCDF_CONFIG=/usr/bin/nf-config
#export   NETCDF_CONFIG=/vortexfs1/apps/impistack-1.0/bin/nf-config

また,以下のようなCONFLICTにおいて,削除すると決めた場合は git rm で,残す場合は git add で対処します.以下は消去の場合です.

CONFLICT (modify/delete): mydir/myfile deleted in main and modified in HEAD. Version HEAD of mydir/myfile left in tree.

git rm mydir/myfile 

編集が完了したら 更新ファイルを add した後,コミット します.コミット時のコメントをファイル毎に変える必要がなければ,すべてのファイルへの対応完了後にまとめてコミットしても構いません.自動マージ可能なファイル(自身では編集しなかったファイル)もコミットする必要があります.

git add file_name  # ファイル毎に
git add -u         # 更新されたファイルをまとめて
git commit -m "comment" 

プルリクエスト(プルリク) で feature を main にマージ

feature での作業が完了し,main に マージ するときは変更理由等をわかりやすく履歴として残すため Github の プリリクエスト を用いることとします.まず,Github (origin) に feature を プッシュ します.

git push origin feature

このプッシュ直後に Github に移ると,Compare & pull request のボタンが一番上に現れていると思います.これをクリックします.現れていない場合は pull request を探して,クリックください.
左側にマージする先,右側に今プッシュしたブランチが現れ,左向きの矢印 ← で繋がれています.左側が目的のマージ先になっているか確認して適切に設定します.おそらくデフォルトは upstream の master リポジトリになっていると思いますので,それが意図したものでなければ修正します.ここでは origin main にしました.
その下のタイトルとコメントを入力し,Create pull request をクリックします.
コンフリクトがなければ下に現れる Merge pull request をクリックし,続けて Confirm merge をクリックします.
上記の流れで行う限り,コンフリクトはローカルで main を feature にマージしたところで解消されているはずですので,この プルリクエスト ではコンフリクトは起こらないはずです.この記事での プルリクエスト の目的はあくまで改変の記録をわかりやすく管理するためです.

ローカルリポジトリの更新

origin/main が更新されましたので,これをローカルリポジトリに反映させます.この過程ではコンフリクトは発生せず,Fast-forward merge となります.

git checkout main
git pull origin main

featureブランチは一旦削除しましょう.必要があれば改めてfeatureブランチを作成しましょう.

git branch -d feature

スパコン専用ブランチの運用

スパコンのローカルリポジトリには永続ブランチの main とスパコン専用ブランチ sc を持たせ,main を sc にマージするものとします(sc を main にマージする場合は上記の通り,Githubのプルリクで対応するものとします).main をチェックアウトし,Github (origin) の main から更新を取り込み,sc にマージします.

git checkout main
git pull origin main
git checkout sc
git merge main

これまでと同様にコンフリクトに対応し,Github (origin) にプッシュします.

git push origin sc

さらに origin/main に取り込む場合は Github のプルリクで対応します.

feature のプッシュを取り消したい場合

こちらこちらを参考に, feature において git reset --soft HEAD^でローカルの変更を残しながらコミットを取り消し,git push origin +feature で origin の feature ブランチへ強制的にプッシュします.なお +feature はfeatureブランチ名の先頭に + を付けており,これが強制を意味します.

Github に SSH接続

ディレクトリ ~/.ssh/ に移動し,秘密鍵と公開鍵を作成します.-t: 暗号化方式を指定,-b: 暗号化強度を指定,-C: コメントを設定 です.

$ ssh-keygen -t rsa -b 4096 -C "username@hoge.com"
Enter file in which to save the key (/home/account/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

秘密鍵のファイル名を求められますが,デフォルトとするため,何も入力せずに Enter を押します.続いて passphrase を2回入力します.

Github にログインし,右上ボタンのプルダウンで SettingsSSH and GPG keys に移動します.右上の New SSH key ボタンをクリックし,Title (ロカールマシン名等,適当な名前)と作成した公開鍵を Key に貼り付け,Add SSH key をクリックします.

秘密鍵を ssh-agent に登録する

passphrase を聞かれますので,入力します.

$ ssh-add ~/.ssh/id_rsa

もしエラーが出たら,以下のように対応します.passphraseの入力が必要です.

Could not open a connection to your authentication agent.
$ eval "$(ssh-agent)"
Agent pid *******
$ ssh-add ~/.ssh/id_rsa
Enter passphrase for id_rsa: 

以下を実行して,passphrase を入力し,Hi your_account! You've successfully authenticated, but GitHub does not provide shell access. のようなメッセージが現れれば成功です.

ssh -T git@github.com

もし以下のようになった場合は yesと回答します.

The authenticity of host 'github.com (**.**.***.***)' can't be established.
ECDSA key fingerprint is ***************************************************.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,**.**.***.***' (ECDSA) to the list of known hosts.
Hi *****! You've successfully authenticated, but GitHub does not provide shell access.

リモートURLがHTTPSの場合の注意

SSH接続に変更しましょう.すでに,他のリポジトリがSSHで接続できている場合は,.git/configを開き,url = の行だけ以下のように書き換えるだけです.

[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	ignorecase = true
[remote "origin"]
	url = git@github.com:***/***.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
	remote = origin
	merge = refs/heads/main

以下は古い情報です
2021年8月13日以降,HTTPSの場合はパスワードではなく,アクセストークンでの認証 が必要になっています.アクセストークンをコピーし,Password for 'https://***@github.com': にペーストします.何も表示されませんが,そのままEnterを入力します.アクセストークンは1ヶ月有効ですが,それが表示されたページから移動すると再表示できません.Githubにログインした状態で こちら で再作成表示できます.

参考資料

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?