git pull
これは、誰かが(または、同等に、git fetch
および)を使用してプロジェクトを更新した結果ですgit merge
。リポジトリが次のようになっていると想像してください。
o --- o ---o[オリジン/マスター]
\
A --- B ---C[マスター]
つまり、元のリポジトリにあったものに加えて、コミットを実行A
しB
ましC
た。
その間に、他の誰かが変更を加えて共有リポジトリにプッシュします。次にリポジトリを実行git fetch
すると、次のようになります。
o --- o --- o --- D --- E ---F[オリジン/マスター]
\
A --- B ---C[マスター]
ここで、実行するとgit merge
(覚えておいてください:の後には)git pull
がgit fetch
続きgit merge
ます。あなたはこれを持っているでしょう:
o --- o --- o --- D --- E ---F[オリジン/マスター]
\\
A --- B --- C ---G[マスター]
すべてがうまくいくと仮定すると、G
おそらく単なる「ばかげた」マージコミットです。技術的には、の状態はととはG
異なるため、別の方法で検討する必要があります。F
C
さて、この変更をプッシュすると、次のようになります。
o --- o --- o --- D --- E --- F
\\
A --- B --- C ---G[オリジン/マスター]
そして、開発を続けると、次のようになります。
o --- o --- o --- D --- E --- F
\\
A --- B --- C ---G[オリジン/マスター]
\
H --- I ---J[マスター]
さて、これを続ければ(そして多くの人がこれを続ければ)、あなたはあなたの写真のような木になってしまうでしょう。これは「間違っている」わけではありませんが、開発履歴を追跡するのが非常に難しいため、多くの人がそれを嫌います。
この問題の解決策は、人々にリベースするように教えることです。リベースすると、(ご指摘のとおり)役に立たないマージコミットがリモートになり、はるかにクリーンな履歴が得られます。上記の場合、線形の開発履歴になります。それをフォローするのははるかに簡単です。ただし、リベースした後、コードを再構築して再テストする必要があることを知っておく必要があります...コードが簡単にマージされたからといって、結果が正しいとは限りません。
中央リポジトリを使用して公式の開発ラインを共有している場合は、これらの自動(「愚かな」/「役に立たない」)マージコミットを検出してプッシュを拒否する事前受信フックを実装できます。 。実際には、フックでデフォルトのマージコミットメッセージを検索する必要があります...したがって、本当にマージコミットを維持したい場合は(場合によってはそれが理にかなっています)、少なくともインテリジェントなコミットメッセージを作成する必要があります。
これがフックの例です。私は余分なものをたくさん取り除いたので、それをテストすることができませんでした。
#!/ bin / bash
#このスクリプトは、Gnomeのpre-receive-check-policyフックに基づいています。
#このスクリプトは、無関係なマージコミットを*のみ*チェックします。
#一部のメッセージで使用
server = git.wherever.com
GIT_DIR = $(git rev-parse --git-dir 2> / dev / null)
in_import(){
test -e "$ GIT_DIR /pending"
}
force(){
test -n "$ GNOME_GIT_FORCE"
}
check_commit(){
commit = $ 1
subject = "$(git log $ commit -1 --pretty = format:%s)"
if expr "$ subject":"。*Mergebranch。*of。*\(git \ | ssh \):"> / dev / null 2>&1; それから
もしも !in_import &&!強制; それから
猫&2
---
コミット:
EOF
git log $ commit -1>&2
猫&2
--rebaseなしで「gitpull」と入力して作成されたようです
ローカルで変更した場合のオプション。'gitpull--rebase'を実行しています
問題を修正します。次に、「gitpush」をもう一度試してください。参照してください:
http://live.gnome.org/Git/Help/ExtraMergeCommits
---
EOF
出口1
fi
fi
}
check_ref_update(){
oldrev = $ 1
newrev = $ 2
refname = $ 3
change_type = update
if expr $ oldrev: "^ 0 \ + $"> / dev / null 2>&1; それから
change_type = create
fi
if expr $ newrev: "^ 0 \ + $"> / dev / null 2>&1; それから
if [x $ change_type = xcreate]; それから
#無効な参照を削除し、許可する
0を返す
fi
change_type = delete
fi
ケース$refnamein
refs / heads / *)
#ブランチの更新
branchname = $ {refname#refs / heads /}
range =
#このブランチアップデートで導入された新しいコミットについては、
#よくある間違いを見つけるためにいくつかのチェックを実行します。
#
#ここでの表現はpost-receive-notify-ciaと同じです。私たちは取る
#リポジトリ内のすべてのブランチ、「^ / ref / heads / branchname」、その他
#実際にコミットしているブランチよりも、コミットを除外する
#間のコミットのリストからそれらのブランチにすでにあります
#$oldrevと$newrev。
if [-n "$ range"]; それから
$(git rev-parse --symbolic-full-name --not --branches|\にマージされた場合
egrep -v "^ \ ^ $ refname $" | \
git rev-list --reverse --stdin "$ range"); 行う
check_commit $ merged
終わり
fi
;;
esac
0を返す
}
if [$#= 3]; それから
check_ref_update $ @
そうしないと
oldrevnewrevrefnameを読みながら; 行う
check_ref_update $ oldrev $ newrev $ refname
終わり
fi
出口0