[解決済み] Gitブランチの最も近い親を見つける方法
質問
例えば、以下のようなローカルリポジトリがあり、コミットツリーが以下のような状態だとします。
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
master
は私の
これは最新の安定版リリースコードです
,
develop
は私の
これは「次の」リリースコードです。
であり、かつ
feature
は
のために準備されている新しい機能です。
develop
.
へのプッシュを拒否できるようにしたい。
feature
をリモートリポジトリにコミットしない限り、私のリモートリポジトリに
f
の直接の子孫である。
develop
HEADです。つまり、コミットツリーはこのようになります。これは、フィーチャーが
git rebase
オン
d
.
master --> a
\
\
develop c --> d
\
\
feature f --> g --> h
ということは、可能なのでしょうか。
-
の親ブランチを特定する。
feature
? -
親ブランチのコミットで
f
の子孫なのか?
そこから、親ブランチのHEADが何であるかをチェックし、次のことを確認します。
f
の前任者が親ブランチの HEAD に一致し、その機能がリベースされる必要があるかどうかを判断します。
解決方法は?
リモートリポジトリに デベロッパー ブランチ (最初の説明ではローカルリポジトリにあると書かれていましたが、リモートにもあるようです) を使用すれば、私が思うようなことを実現できるはずですが、その方法はあなたが思い描いているものとは少し異なります。
Gitの歴史は DAG のコミットです。ブランチ(および一般的な「参照」)は、継続的に増加するコミット DAG の特定のコミットを指す一時的なラベルにすぎません。そのため、ブランチ間の関係は時間の経過とともに変化しますが、コミット間の関係は変化しません。
---o---1 foo
\
2---3---o bar
\
4
\
5---6 baz
次のように表示されます。
baz
は、(古いバージョンの)
bar
? しかし、もし
bar
?
---o---1 foo
\
2---3
\
4
\
5---6 baz
これで、次のようになります。
baz
がベースになっています。
foo
. しかし、その祖先は
baz
は変更されませんでした。私たちはラベルを削除しただけです(その結果、ぶら下がったコミットも削除されました)。で新しいラベルを追加したらどうでしょう。
4
?
---o---1 foo
\
2---3
\
4 quux
\
5---6 baz
これで、次のようになります。
baz
がベースになっています。
quux
. それでも、祖先は変わらず、ラベルだけが変わりました。
しかし、もし「コミットが
6
の子孫である。
3
?" (仮に
3
と
6
が完全なSHA-1コミット名である場合)、答えは「イエス」でしょう。
bar
と
quux
ラベルが存在するかどうか。
そこで、「押されたコミットは、現在の先端の デベロップ ブランチ? "といった質問をすることはできますが、"プッシュされたコミットの親ブランチは何か? "といった質問を確実にすることはできません。
あなたが望むものに近いと思われる、ほとんど信頼できる質問は、次のとおりです。
プッシュされたコミットのすべての先祖(現在の先端である 開発 とその祖先)で、現在の先端が デベロップ を親とする。
- そのようなコミットが少なくとも1つ存在するか?
- そのようなコミットはすべて単一の親コミットですか?
というように実装することができる。
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_children_of_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
,) echo "must descend from tip of '$basename'"
exit 1 ;;
,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
exit 1 ;;
,*) exit 0 ;;
esac
これは、制限されたいことの一部をカバーしますが、すべてではないかもしれません。
参考までに、拡張履歴の例を示します。
A master
\
\ o-----J
\ / \
\ | o---K---L
\ |/
C--------------D develop
\ |\
F---G---H | F'--G'--H'
| |\
| | o---o---o---N
\ \ \ \
\ \ o---o---P
\ \
R---S
上記のコードで
H
と
S
を受け入れながら
H'
,
J
,
K
または
N
を受け付けるが
L
と
P
(の先端をマージすることはありません)。
開発
).
も拒否すること
L
と
P
というように、質問を変更することができます。
プッシュされたコミットのすべての先祖 (現在の先端である 開発 とその祖先)。
- 親が2つあるコミットはありますか?
- そうでない場合、そのようなコミットの少なくとも 1 つは、現在の tip が 開発する その(唯一の)親は?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
echo "'$basename' is missing, call for help!"
exit 1
fi
parents_of_commits_beyond_base="$(
git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
*\ *) echo "must not push merge commits (rebase instead)"
exit 1 ;;
*"$baserev"*) exit 0 ;;
*) echo "must descend from tip of '$basename'"
exit 1 ;;
esac
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] git pull」と「git fetch」の違いは何ですか?
-
[解決済み] コミット前に 'git add' を取り消すにはどうすればよいですか?
-
[解決済み] リモートのGitブランチをチェックアウトするには?
-
[解決済み] 現在のGit作業ツリーからローカル(未追跡)ファイルを削除する方法
-
[解決済み] git rebase の取り消し
-
[解決済み] Git で最新のコミットを新しいブランチに移動する
-
[解決済み】既存のGitブランチをリモートブランチに追従させる?
-
[解決済み】ローカルのGitブランチの名前を変更するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】以下の追跡されていないワーキングツリーファイルは、マージによって上書きされますが、私は気にしません。
-
[解決済み】gitが「変更をコミットするか、マージする前にstashしてください」と言うのを解決するには?
-
[解決済み】git push >> fatal: 設定されたプッシュ先がありません。
-
git push reports an error ! [リモート拒否] master -> master (受信前のフックが拒否されました)
-
gitアップロードの共通エラー処理
-
[解決済み] リモートから<branch name>とマージするように構成が指定されていますが、そのような参照は取得されませんでしたか?
-
[解決済み] あなたのブランチは 'origin/master' より 3 コミット進んでいます。
-
[解決済み] TortoiseGitで「git did not exit cleanly (exit code 128)」というエラーを解決するには?[クローズド]
-
[解決済み] Gitのフォルダ構造で変更・追加されたファイルのみをエクスポートする機能
-
[解決済み] Gitのプッシュエラーです。Unable to unlink old (Permission denied)です。