私はgithubに他の誰か(ボブ、議論のために)がプルリクエストを発行したリポジトリを持っています。彼のコードは完全ではないため、数回のマークアップを行います。私が理解しているように、彼はマークアップされた変更のセットごとにコミットし、プルリクエストにプッシュします。
だから私のリポジトリは次のようになります:
master: ---o A (Chowlett
|
|
pull-req: o---o---o---o
B C D (all Bob)
コミットSHAおよびメッセージは次のとおりです。
A:
123456 Good commit <chowlett>
B:
777ccc Fix the widget bug <bob>
C:
888ddd Review markups <bob>
D:
999eee Further markups <bob>
私は今、このプルリクエストを受け入れて満足しています。しかし、私はむしろ事前マークアップバージョンが私のリポジトリにないことを望みます。次のすべてを達成できますか?そしてどうやって?
ボブはGitHub PRを作成しているときにコミットを押しつぶす必要がないことに注意してください。
2016年3月以降、PRを受け入れるメンテナ(あなた)にその操作を任せることができます。
" Squash your commits "とその 新しいドキュメント を参照してください
これは、マージボタンを使用してマージされたすべてのプルリクエストに対して強制的にスカッシュを強制できる新しいオプションです。
git
には、2つの「スカッシュ」関数が組み込まれています。 git merge --squash
があり、git rebase --interactive
にはsquash
アクションがあります。前者は作者や日付の情報を保持せず、一連のコミットからすべての変更をローカルの作業コピーに収集するだけです。後者は対話を必要とするため、迷惑です。
git squash
拡張子 は必要なことを行います。現在のHEADを指定したベースにリベースし、その間にコミットを自動的に押しつぶします。また、リベースが失敗した場合に、最後の押しつぶされたコミットにメッセージを設定するコマンドラインオプションを提供しますt衝突を引き起こします。
これを hub
および ghi
と一緒に投げると、次の行に沿ってスクリプトを作成できる場合があります。
git pull upstream master
hub checkout https://github.com/$user/$repo/pull/$issue
git squash master
rev=$(git rev-parse --short HEAD)
git checkout master
git merge $rev
git commit --amend "Merged pull request #$issue"
git Push upstream master
ghi close $issue $user/$repo
ghi comment $issue "Merged as $rev" $user/$repo
マージには--squashオプションを使用できます
git merge <remote url> <remote branch> --squash
ただし、これはマージコミットを生成しません。代わりに、手動ですべての変更をコピーに適用した場合と同じように、通常の作業ツリーの変更セットを生成します。その後、通常どおりにコミットします。
欠点は、マスターの履歴にこのコミットが彼のブランチからのマージとして表示されないことです。それはあなたが自分で仕事をしたように見え、ボブにクレジットを与えません。
1つのアイデアは、ブランチをチェックアウトし、反復リベースを使用してすべてのコミットを1つに押しつぶし、Pushにプルリクエストを更新させてマージすることです(ただし、この作業の一部をBobに委任することもできます)。
ブランチから最初のコミットにすべてのコミットを自動的に押しつぶし、これをプルリクエストに適用するには、次のコマンドを使用できます。
$ git checkout pull-req
$ GIT_SEQUENCE_EDITOR='sed -i "2,\$s/^pick/s/g" $1' git rebase -i Origin/master
$ git Push --force
GIT_SEQUENCE_EDITOR は、リベースコミットリストの一時エディターを設定するためのGit環境変数です。最初の行(pick
パターンの2,\$
)を除くすべての行の先頭で、Wordのs
をsquash
(つまりsed
)に置き換えるインラインスクリプトに設定します。スクリプトに渡されるコミットリストは、単純なテキストファイルです。その後、Gitはリベースを続行し、最終的なコミットメッセージを編集できるようにします。
また、gitフックを使用すると、この最終メッセージを必要に応じて多かれ少なかれ簡単に編集できます(たとえば、押しつぶされたコミットのメッセージの間に視覚的な区切りを追加します)。
git merge --squash
を使用してスカッシュすることもできます。 2つの方法の違いについては こちら を参照してください。以下のスクリプトは、mergeコマンドを使用して、ブランチのコミットを1つのコミットに押しつぶします。また、ブランチのバックアップも作成します(念のため)。
MAINBRANCH="master"
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# update current feature branch with master
git pull Origin $MAINBRANCH
# delete existing backup
git branch -D "$CURRENT_BRANCH-backup"
# backup current feature branch and go back
git checkout -b "$CURRENT_BRANCH-backup" && git checkout -
# checkout and update master branch
git checkout $MAINBRANCH && git pull
# create new branch from master
git checkout -b "$CURRENT_BRANCH-squashed"
# set it to track the corresponding feature branch
git branch "$CURRENT_BRANCH-squashed" --set-upstream-to "$CURRENT_BRANCH"
# merge and squash the feature branch into the one created
git merge --squash $CURRENT_BRANCH
# commit the squashed changes
git commit
# force Push to the corresponding feature branch
git Push -f . HEAD:$CURRENT_BRANCH
# checkout the feature branch
git checkout $CURRENT_BRANCH
# delete the squashed copy
git branch -D "$CURRENT_BRANCH-squashed"
これでうまくいきました。
devtools_import_export
での私の仕事はそのまま残ります。issue35squashed
のプルリクエストには、コミットが1つしかありません。これが私が実際に行ったことです( https://github.com/anaran/devtools-snippets/network を参照)
git checkout master
git status # all clean
git checkout -B issue35squashed master
git merge --squash devtools_import_export
git status # looks good
git commit # review and commit via emacs
git log --graph --abbrev-commit --stat --pretty --decorate=full --branches
git Push --all -v
(git merge --no-ff ...
を使用した私の以前の試みはissue35take2
にあり、そのプルリクエストにはdevtools_import_export
からの個々のコミットがすべて含まれています。不正解です。)