1

現在のワークフローには、主な git ブランチが 2 つあります。

master- 安定版リリース ブランチ

testing- 全員が自分のコードをテストしましたか

現在、すべての開発者は、開発する機能ごとに新しいブランチを作成しています。完了したら、それを にマージしtesting、QA で問題がないと判断されたら、ブランチを にマージし、master本番環境にデプロイします。

時間が経つにつれて、私たちのtestingブランチは本番環境に到達しないコミットで汚染されます。放棄された機能、修正された代わりに書き直されたものなど。

ある程度一貫した状態を保つためmasterに、時々testing「リセット」したいと思います。testing現時点では、 から完全に削除testingして再分岐することでそうしていmasterます。

ここでの大きな問題は、すべての開発者が自分のローカルtestingブランチを削除し、その新しいコピーをチェックアウトする必要があることです。1 人の開発者がそれをするのを忘れて、再びテストにプッシュした場合、取り除こうとしているすべてのダーティ コミットが戻ってきます。

サーバー上のブランチをリセットして、すべてのユーザーに配布する方法はありますか?

許容できる解決策はtesting、ローカルでリセットを行わないと、ブランチをプッシュできない状態にすることです。しかし、私はそれを行う方法を考えることはできません。

masterコミット間の差分を作成し、testingコミットを元に戻すことはオプションではありません。これにより、これらの各コミットが再びテストに入るのを防ぐことができます。

git pull理想的には、このリセットを定期的に実行するスクリプトがあり、各ユーザーのローカル環境で対話 (を除く) は必要ありません。

4

4 に答える 4

2

時間が経つにつれて、私たちのテスト ブランチは本番環境に到達しないコミットで汚染されます。放棄された機能、修正された代わりに書き直されたものなど。

これはどのように可能ですか?明らかに、機能が放棄された場合は、テスト ブランチからも削除する必要があります。基本的に、テストブランチが時間の経過とともに汚染されると言うと、テストブランチの目的全体が無効になります。これは、本番環境にプッシュしたいコードを表していないものをテストしているためです。

何かがうまくいかない場合、開発者は変更を元に戻し、変更が元に戻されるテスト ブランチにコミットをプッシュする必要があります。

あなたのシナリオでは、テストから本番にすべてマージするか、まったくマージしないでください。

于 2015-02-25T00:46:20.887 に答える
2

短い答えは「いいえ、それはできません」です。

各クローンは完全なスタンドアロン エンティティ1であり、クローン元のソース リポジトリとほとんど変わらないことにorigin注意してください。2 誰かがという名前のブランチをピックアップして、testingそれを呼び出したらorigin/testing:

  • 彼らはあなたが彼らに与えたコミットを持っています。と
  • origin/testingリモートに接続すると、git が自動的に更新され、指示された場合はプルーニング (削除)されるという名前の参照 (「リモート追跡ブランチ」)がありoriginます。

ここまでは順調で、この「自動プルーニング」アクションは素晴らしいと思います。remote.origin.pruneに設定するように説得できる場合true

$ git config remote.origin.prune true

という名前のブランチを削除すると、次のブランチで自動的に消えます。testing origin/testinggit fetch origin

という名前のブランチ作成するときに問題が発生しますtesting。彼らの gitは、彼らが要求しない限り、このブランチを削除しません。彼らの git に関する限り、プライベート ブランチはプライベート ブランチです。git に private を削除するよう説得することができないのと同様に、git に private を削除するよう説得することもできません。彼らはそれを作成しました。それは彼らのリポジトリです。彼らはそれを管理しています。testingexperiment-22

(彼らは自動プルーニングも制御していることに注意してください。なぜなら、彼らはいつでも離れたり、離れたりすることができるからです。git configその設定は彼らの便宜のためのものであり、あなたのものではありません。初期のデフォルト設定は、実行時に作成されたものです。)remote.origin.prunefalseremote.origin.fetchgit fetchgit clone

すべての開発者にこのブランチ ラベルの独自の制御された削除またはクリーニングを行わせる場合は、このモデルを続行できます。しかし、それは行くべき道ではありません。代わりに、別のモデルを使用する必要があります。つまり、開発者が行っている新しい (そして異なる) 開発ライン用に、新しい別のブランチ ラベルを作成します。

たとえば、dev-feature-X機能 X に取り組むために開発者全員が共有できる一時的なブランチを持っている場合があります。すべての作業が完了したら、それを保持または自由に削除すると、開発者は削除を自動的に取得します (剪定の設定) または彼らの余暇ではないです。一方dev-feature-Y、機能 Y などの作業のために開発者全員が共有できる一時的なブランチとして作成しました。


1少なくとも、ここでは当てはまらない「浅い」クローンなどの特殊なケースは無視します。

2なしでクローンを作成すると、ソースのブランチがリモート ブランチになり、ローカル ブランチをチェックアウトするまで (通常はコマンドの最後のステップとして)--mirrorローカル ブランチはまったくありません。また、クローンはソースのフックを認識できないため、それらはクローンされません。のアイテムなど、ディレクトリ内のその他の特別な状態もありません。ただし、これらのいずれも、通常のブランチの使用の原則には影響しません。masterclone.git.git/info

于 2015-02-25T00:52:51.700 に答える
1

1 つのオプションは、特別な方法でマスター ブランチにマージすることにより、開発ブランチの状態をリセットすることです。

git checkout master
git checkout -b new_testing
git merge -s ours testing # this creates a merge commit, but
                          # its tree is that of the current work-tree
                          # which in our case is the same as master
git checkout testing
git merge ours_testing
git branch -d new_testing

new_testingマージ戦略oursは他のツリーではなく現在のツリーを保持し、同等のtheirs戦略がないため、一時的なブランチを作成する必要があります。

この後、次のようなブランチ構造になります

*         (testing) merge
|\
| *       (master) last commit on master
* |       last commit on testing
| |

ただし、テストの内容はマスターの内容と一致します。

これの利点は、後に行われたテストでローカルコミットを持っている人は誰でも、変更を通常どおりlast commit on testingにリベースできることです。origin/testing

これは通常の開発フローを妨げてはならないので、頻繁に (毎晩?) 実行できない理由はありません。

于 2015-02-25T01:10:06.053 に答える
1

ある開発者が [リベース] を忘れて再度プッシュすると、取り除こうとしているtesting[放棄されたヒントから] すべてのダーティ コミットが戻ってきます。testing

他の人のリポジトリで何が起こっているかを制御することはできませんが、彼らが自分のリポジトリに何をプッシュするかは制御できます。

許容できる解決策は、テスト ブランチを、ローカルでリセットを行わないと誰もプッシュできない状態にすることです。しかし、私はそれを行う方法を考えることはできません。

この事前受信フックは、マージを介して不要な履歴を導入するプッシュを拒否します。

#!/bin/sh
#  Do not permit merges from unwanted history
#set -x
err=0
while read old new ref; do              # for each pushed ref

        [[ ${old%[^0]*} = $old ]] && continue # new branches aren't checked.

        nomerge=$(git for-each-ref refs/do-not-merge --format='%(objectname)^!')

        if [[ $( git rev-list --count --ancestry-path --boundary $old..$new $nomerge
         ) != $( git rev-list --count --ancestry-path --boundary $old..$new ) ]]; then
                echo "$ref doesn't allow merges from outdated history"
                err=1
        fi
done
exit $err

# why it works:

# if adding nomerge commits' parents as ancestors has any effect, then the
# nomerge commits are reachable without going through $old, i.e. they're 
# in some merged history. So check whether adding the abandoned commits as
# explicit ancestors to the push makes them show up, and refuse it if so.

不要なコミットをマークするにはrefs/do-not-merge、たとえばの下でそれらを参照してください

git config alias.no-further-merges-from \
  '!f() { git update-ref "refs/do-not-merge/$1-@`date +%Y-%m-%dT%H%M%S`" "$1"; }; f'

だから、放棄の儀式testing

git no-further-merges-from testing
git checkout -B testing master

以前に放棄されたヒントをマークしたい場合は、sha またはその他の表現でそれらを参照できます。

git no-further-merges-from 'testing@{last october 31}'
于 2015-02-25T02:24:10.410 に答える