[解決済み] 過去のコミットを簡単に修正するには?
質問
私は今 git の過去のコミットで一つのファイルを修正する を読みましたが、残念ながらその解決策はコミットを「並べ替える」もので、私が望んでいるものではありません。そこで質問です。
時々、私は (無関係な) 機能に取り組んでいるときに、私のコードのバグに気づきます。迅速な
git blame
を実行すると、そのバグが数コミット前に導入されたことがわかります (私はかなりたくさんコミットするので、通常はバグを導入したのが最新のコミットではないのです)。この時点で、私は通常これを行います。
git stash # temporarily put my work aside
git rebase -i <bad_commit>~1 # rebase one step before the bad commit
# mark broken commit for editing
vim <affected_sources> # fix the bug
git add <affected_sources> # stage fixes
git commit -C <bad_commit> # commit fixes using same log message as before
git rebase --continue # base all later changes onto this
しかし、このようなことが頻繁に起こるので、上記のようなシーケンスが煩わしくなってきました。特に'interactive rebase'は退屈です。上記の手順で、過去の任意のコミットをステージングされた変更で修正できるようなショートカットはないでしょうか?これが履歴を変えることは完全に承知していますが、私はあまりにも頻繁に間違いを犯すので、次のようなものが本当に欲しいのです。
vim <affected_sources> # fix bug
git add -p <affected_sources> # Mark my 'fixup' hungs for staging
git fixup <bad_commit> # amend the specified commit with staged changes,
# rebase any successors of bad commit on rewritten
# commit.
plumbing toolsなどを使ってコミットを書き換えるようなスマートなスクリプトとか?
どのように解決するのですか?
解答を更新しました。
少し前に、新しい
--fixup
引数が追加され
git commit
に適したログメッセージを含むコミットを作成するために使用されます。
git rebase --interactive --autosquash
. つまり、過去のコミットを修正する最も簡単な方法は、現在では
$ git add ... # Stage a fix
$ git commit --fixup=a0b1c2d3 # Perform the commit to fix broken a0b1c2d3
$ git rebase -i --autosquash a0b1c2d3~1 # Now merge fixup commit into broken commit
オリジナル回答
これは、私がしばらく前に書いた小さなPythonスクリプトで、これを実装しています。
git fixup
ロジックを実装したものです。このスクリプトは、あなたがいくつかの変更をステージングし、それらの変更を与えられたコミットに適用すると仮定しています。
注意
: このスクリプトは Windows 固有のもので、以下のものを探します。
git.exe
を探し、それを
GIT_EDITOR
を使用して環境変数を設定します。
set
. 他のオペレーティングシステムでは、必要に応じて調整してください。
このスクリプトを使うことで、私が求めた「壊れたソースの修正、修正の段階、git fixupの実行」というワークフローを正確に実装することができます。
#!/usr/bin/env python
from subprocess import call
import sys
# Taken from http://stackoverflow.com/questions/377017/test-if-executable-exists-in python
def which(program):
import os
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
if len(sys.argv) != 2:
print "Usage: git fixup <commit>"
sys.exit(1)
git = which("git.exe")
if not git:
print "git-fixup: failed to locate git executable"
sys.exit(2)
broken_commit = sys.argv[1]
if call([git, "rev-parse", "--verify", "--quiet", broken_commit]) != 0:
print "git-fixup: %s is not a valid commit" % broken_commit
sys.exit(3)
if call([git, "diff", "--staged", "--quiet"]) == 0:
print "git-fixup: cannot fixup past commit; no fix staged."
sys.exit(4)
if call([git, "diff", "--quiet"]) != 0:
print "git-fixup: cannot fixup past commit; working directory must be clean."
sys.exit(5)
call([git, "commit", "--fixup=" + broken_commit])
call(["set", "GIT_EDITOR=true", "&&", git, "rebase", "-i", "--autosquash", broken_commit + "~1"], shell=True)
関連
-
[解決済み] Git で直近のローカルコミットを取り消すには?
-
[解決済み] Gitブランチをローカルやリモートで削除するには?
-
[解決済み] コミット前に 'git add' を取り消すにはどうすればよいですか?
-
[解決済み] リモートのGitブランチをチェックアウトするには?
-
[解決済み] 既存の、プッシュされていないコミットメッセージを修正するには?
-
[解決済み] Git リポジトリを以前のコミットに戻すにはどうすればよいですか?
-
[解決済み] 現在のGit作業ツリーからローカル(未追跡)ファイルを削除する方法
-
[解決済み] Git が追跡したファイルを .gitignore に登録したまま「忘れる」ようにするにはどうしたらいいですか?
-
[解決済み] 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がローカルバージョンをリモートバージョンに置き換える
-
[解決済み】マージが終了していません(MERGE_HEADは存在します)。
-
[解決済み] リモートから<branch name>とマージするように構成が指定されていますが、そのような参照は取得されませんでしたか?
-
[解決済み] LFはgitでCRLFに置き換えられます - それは何ですか、そしてそれは重要ですか?[重複]。
-
[解決済み] TortoiseGitで「git did not exit cleanly (exit code 128)」というエラーを解決するには?[クローズド]
-
[解決済み] VSTS Git Fetch Failed with exit code: 128
-
[解決済み] git initを2回実行すると、リポジトリが初期化されますか?それとも既存のリポジトリを再初期化しますか?
-
[解決済み] Git で最新のコミットを新しいブランチに移動する
-
[解決済み】Pythonで実行可能ファイルが存在するかどうかをテストしますか?