Fork プロジェクトを使用して自分自身の変更を行うと、自分の貢献を簡単に統合することができますが、これらの変更を上流に戻さない場合、つまり親リポジトリに戻さない場合、それらを追跡することができなくなる可能性があります。これにより、異なるラインがリポジトリに表示される可能性があります。すべての貢献者が同じ情報を取得できるようにするために、git forking と git upstream の相互作用についていくつかの基本的な原則を理解する必要があります。このブログでは、基本的な知識、トラブルシューティング、さらにはクールな小技を紹介します。
Git Upstream: 最新の変更を保持して貢献する#
まず、一般的な設定と基本的なワークフローについて詳しく説明します。
通常、origin と upstream の 2 つのリモートがあります。upstream はプロジェクトの管理者であり、またあなたが貢献したい本当のソースです。
まず、upstream リモートを設定し、origin も設定していることを確認します。
$ git remote -v
origin [email protected]:my-user/some-project.git (fetch)
origin [email protected]:my-user/some-project.git (push)
もしまだ upstream がない場合は、簡単にリモートコマンドで追加できます。
git remote add upstream [email protected]:some-gatekeeper-maintainer/some-project.git
リモートが正しく追加されたかどうかを確認します。
git remote -v
origin [email protected]:my-user/some-project.git (fetch)
origin [email protected]:my-user/some-project.git (push)
upstream [email protected]:some-gatekeeper-maintainer/some-project.git (fetch)
upstream [email protected]:some-gatekeeper-maintainer/some-project.git (push)
これで、upstream リポジトリの最新の変更を取得するために fetch を使用できます。更新を取得したい場合は、この操作を繰り返します。
(プロジェクトのタグがマージされていない場合は、git fetch upstream --tags
も実行する必要があります)
git fetch upstream
通常、ローカルブランチを上流のメインブランチの近似ミラーとして保持し、機能ブランチで作業を行います。これらのブランチは後でプルリクエストになる可能性があるためです。
この時点で、マージまたはリベースを使用することは重要ではありません。結果は通常同じです。マージを使用しましょう。
git checkout master
git merge upstream/master
上流のメンテナにいくつかの作業を共有したい場合は、マスターブランチから機能ブランチを作成し、満足したらリモートリポジトリにプッシュします。
リベースを使用することもできますが、その後マージして上流にクリーンなコミット(最善は 1 つ)があることを確認するために行います。
git checkout -b feature-x
# いくつかの作業とコミットが行われます
# しばらく時間が経過します git fetch upstream
git rebase upstream/master
複数のコミットを 1 つにまとめる必要がある場合は、この時点で強力な rebase インタラクティブを使用できます。
git fork で公開する#
上記の手順を経て、単純な push でリモートフォークに作業を公開できます。
git push origin feature-x
リモートブランチ feature-x を公開した後、上流メンテナからのフィードバックに基づいて更新する必要がある場合、次のような小さな問題が発生します。
- 新しいブランチを作成し、あなたと上流の更新を含めます
- 上流の更新をローカルブランチにマージし、マージコミットを記録します。これにより、上流のリポジトリが上流の更新を元に再構築されます。そして、リモートブランチに強制プッシュします。
git push -f origin feature-x
私は個人的には、履歴をきれいに保つことを好み、オプション 3 を選択しますが、異なるチームには異なるワークフローがあります。注意:自分のフォークを使用している場合にのみ、これを行うことができます。共有リポジトリとブランチの履歴を書き換えることは絶対に行ってはいけません。
今日のヒント:プロンプトに先行 / 遅行の数を表示する#
fetch 後、git status はリモートブランチと比較してあなたが先行または遅行しているコミットの数を表示します。これらの情報を忠実なコマンドプロンプトで表示できたら、もっと良いですよね?私もそう思いましたので、私は私の bash の箸を使ってそれを作りました。
以下は、設定が完了した後、プロンプトに表示されるものです:
nick-macbook-air:~/dev/projects/stash[1|94]$
これを.bashrc または同等のものに追加する必要があるものです。ただの関数です:
function ahead_behind {
curr_branch=$(git rev-parse --abbrev-ref HEAD);
curr_remote=$(git config branch.$curr_branch.remote);
curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
}
この新しい関数 ahead_behind を使用して、望むように bash プロンプトをカスタマイズできます。色付けの作業は読者にお任せします。
サンプルプロンプト:
export PS1="\h:\w[\$(ahead_behind)]$"
内部構造#
詳細や説明が好きな人のために、これがどのように機能するかを説明します。
現在の HEAD のシンボル名と現在のブランチを取得します。
curr_branch=$(git rev-parse --abbrev-ref HEAD);
現在のブランチが指すリモートを取得します。
curr_remote=$(git config branch.$curr_branch.remote);
このリモートブランチがマージされるべきブランチを取得します(最後のスラッシュ [/] を含むすべての内容を削除するための安価な Unix のトリックを使用します)。
curr_merge_branch=$(git config branch.$curr_branch.merge | cut -d / -f 3);
これで、先行と遅行のコミット数を収集するために必要なものが揃いました。
git rev-list --left-right --count $curr_branch...$curr_remote/$curr_merge_branch | tr -s '\t' '|';
古い Unix の tr コマンドを使用して、タブを区切り文字 | に変換します。
git upstream の始め方#
これが git upstream の基本的な手順です。git upstream の設定方法、新しいブランチの作成方法、変更の収集方法、git fork を使用しての公開方法、そしてリモートブランチが先行または遅行している回数を表示する便利なヒントについて説明しました。