ステージングした変更だけを隠しておく方法はありますか?私が問題を抱えているシナリオは、ある時点でいくつかのバグに取り組み、ステージングされていない変更がいくつかある場合です。これらのファイルを個別にステージングし、.patchファイルを作成し、コードが承認されるまでそれらを隠しておきたいと思います。このようにして、承認されたら、(現在の)セッション全体を隠し、そのバグをポップしてコードをプッシュできます。
私はこれについて間違った方法で行っていますか?プロセスを単純化するためにgitが他の方法でどのように機能するかを誤解していますか?
はい、信じられないかもしれませんが、本当に可能ですDOUBLE STASH:
git stash --keep-index
を実行します。このコマンドは、変更のALL(stagedおよびunstaged)でスタッシュを作成しますが、ステージングされた変更は残します作業ディレクトリ内(まだステージングされた状態)。git stash save "good stash"
を実行します"good stash"
にステージングファイルのみが追加されました。Stashの前にステージングされていないファイルが必要な場合は、最初のstash(--keep-index
で作成されたもの)を適用するだけで、"good stash"
に隠したファイルを削除できます。
楽しい
最新のgitでは、--patch
オプションを使用できます
git stash Push --patch
また、gitは、stashに追加するかどうかをファイルの各変更について尋ねます。 y
またはn
と答えるだけです
現在ステージングされているもののみを隠し、他のすべてを残すスクリプトを作成しました。これは、無関係な変更をあまりにも多く開始し始めたときにすごいことです。目的のコミットに関係のないものをステージングして、それだけを隠してください。
(出発点のBartłomiejに感謝)
#!/bin/bash
#Stash everything temporarily. Keep staged files, discard everything else after stashing.
git stash --keep-index
#Stash everything that remains (only the staged files should remain) This is the stash we want to keep, so give it a name.
git stash save "$1"
#Apply the original stash to get us back to where we started.
git stash apply stash@{1}
#Create a temporary patch to reverse the originally staged changes and apply it
git stash show -p | git apply -R
#Delete the temporary stash
git stash drop stash@{1}
特定のバグの変更をコミットし、そのコミットとその前身からパッチを作成してみませんか?
# hackhackhack, fix two unrelated bugs
git add -p # add hunks of first bug
git commit -m 'fix bug #123' # create commit #1
git add -p # add hunks of second bug
git commit -m 'fix bug #321' # create commit #2
次に、適切なパッチを作成するには、git format-patch
を使用します。
git format-patch HEAD^^
これにより、2つのファイルが作成されます:0001-fix-bug-123.patch
および0002-fix-bug-321.patch
または、バグごとに個別のブランチを作成して、バグ修正を個別にマージまたはリベースしたり、うまくいかない場合は削除したりすることもできます。
このシナリオでは、問題ごとに新しいブランチを作成することを好みます。プレフィックスtemp /を使用しているので、後でこれらのブランチを削除できることがわかります。
git checkout -b temp/bug1
Bug1を修正するファイルをステージングしてコミットします。
git checkout -b temp/bug2
その後、必要に応じて各ブランチからコミットを選択し、プルリクエストを送信できます。
同じことを達成するには...
git commit -m 'temp'
git add .
git stash
git reset HEAD~1
ブーム。不要なファイルは隠されています。必要なファイルはすべて用意されています。
git stash --keep-index
は良い解決策です...削除されたパスで正しく機能しなかった点を除き、Git 2.23(Q3 2019)で修正されました
commit b932f6a (2019年7月16日)by Thomas Gummerer(tgummerer
) を参照してください。
( 浜野潤二-gitster
- in commit f8aee85 、2019年7月25日)
stash
:--keep-index
で削除されたファイルの処理を修正
git stash Push --keep-index
は、インデックスとディスクの両方で、インデックスに追加されたすべての変更を保持することになっています。現在、ファイルがインデックスから削除されると、これは正しく動作しません。
ディスク上で削除したままにする代わりに、**-keep-indexは現在ファイルを復元します。**インデックスと作業ツリーを忠実に復元できる非オーバーレイモードで「
git checkout
」を使用して、この動作を修正します。
これにより、コードも簡素化されます。追跡されていないファイルがインデックスで削除されたファイルと同じ名前を持っている場合、これは追跡されていないファイルを上書きすることに注意してください。
一度にいくつかのバグに取り組むことが絶対に必要ですか? 「一度に」とは、「複数のバグに対して同時にファイルを編集する」ことを意味します。あなたが絶対にそれを必要としない限り、私はあなたの環境で一度に一つのバグだけに取り組むだろうからです。そうすれば、ローカルブランチとリベースを使用できます。これは、複雑なスタッシュ/ステージを管理するよりもはるかに簡単です。
マスターがコミットBにいるとしましょう。今度はバグ#1に取り組みます。
git checkout -b bug1
今、あなたはブランチbug1にいます。いくつかの変更を行い、コミットし、コードレビューを待ちます。これはローカルなので、他の人に影響を与えることはなく、git diffsからパッチを作成するのに十分簡単なはずです。
A-B < master
\
C < bug1
今、あなたはbug2に取り組んでいます。 git checkout master
でマスターにbackします。新しいブランチgit checkout -b bug2
を作成します。変更を行い、コミットし、コードレビューを待ちます。
D < bug2
/
A-B < master
\
C < bug1
あなたがレビューを待っている間に、他の誰かがmasterでE&Fをコミットするふりをしましょう。
D < bug2
/
A-B-E-F < master
\
C < bug1
コードが承認されたら、次の手順でマスターにリベースできます。
git checkout bug1
git rebase master
git checkout master
git merge bug1
これにより、次の結果が得られます。
D < bug2
/
A-B-E-F-C' < master, bug1
次に、プッシュし、ローカルのbug1ブランチを削除して、外に出ます。ワークスペースには一度に1つのバグがありますが、ローカルブランチを使用すると、リポジトリで複数のバグを処理できます。これにより、複雑なステージ/スタッシュダンスが回避されます。
コメント内のctoteの質問への回答:
バグごとにスタッシングに戻り、一度に1つのバグのみを処理できます。少なくとも、ステージングの問題を回避できます。しかし、これを試してみたところ、個人的には面倒です。隠し場所はgit logグラフでは少し乱雑です。さらに重要なのは、何かを台無しにした場合、元に戻せないことです。作業ディレクトリが汚れていて、スタッシュをポップした場合、そのポップを「元に戻す」ことはできません。既存のコミットを台無しにするのははるかに困難です。
git rebase -i
。
あるブランチを別のブランチにリベースすると、インタラクティブに実行できます(-iフラグ)。これを行うとき、各コミットで何をしたいかを選択するオプションがあります。 Pro Gitは、HTML形式でもオンラインで公開されている素晴らしい本であり、リベースとスカッシュに関する素敵なセクションがあります。
http://git-scm.com/book/ch6-4.html
便宜上、サンプルを逐語的に盗みます。次のコミット履歴があると仮定し、bug1をmasterにリベースおよびスカッシュします。
F < bug2
/
A-B-G-H < master
\
C-D-E < bug1
git rebase -i master bug1
と入力すると、次のように表示されます
pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
ブランチのすべてのコミットを単一のコミットにまとめるには、最初のコミットを「pick」のままにして、後続の「pick」エントリをすべて「squash」または単に「s」に置き換えます。コミットメッセージを変更する機会も得られます。
pick f7f3f6d changed my name a bit
s 310154e updated README formatting and added blame
s a5f4a0d added cat-file
#
# Commands:
# p, pick = use commit
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
ええ、つぶすのは少し苦痛ですが、隠し場所を多用するよりも、それをお勧めします。
Mike Monkiewiczの回答に対するコメントから、より単純なモデルを使用することをお勧めします。通常の開発ブランチを使用しますが、マスターブランチで単一のコミットを取得するにはマージのスカッシュオプションを使用します。
git checkout -b bug1 # create the development branch
* hack hack hack * # do some work
git commit
* hack hack hack *
git commit
* hack hack hack *
git commit
* hack hack hack *
git commit
git checkout master # go back to the master branch
git merge --squash bug1 # merge the work back
git commit # commit the merge (don't forget
# to change the default commit message)
git branch -D bug1 # remove the development branch
この手順の利点は、通常のgitワークフローを使用できることです。