banner
davirain

davirain

twitter
github
知乎
twitter

Gitフォークとアップストリーム:クールなトリックのやり方

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 での公開、そしてリモートブランチが先行 / 遅行している回数を表示する便利なヒントについて説明しました。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。