3

私が持っているもの:

---A----B-----C-----D--------*-----E-------> (master)
                     \      /
                      1----2 (foo)

必要なもの:

---A---------------D--------*-----E-------> (master)
                    \      /
                     1----2 (foo)

少し前に、自分の git リポジトリから削除したい 2 つのコミットを行いました。さまざまなリベース「チュートリアル」を試しましたが、それらはすべて奇妙な git 履歴で終わったので、サンプル リポジトリを作成しましたが、結果は期待したものではありません。私が欠けているものを理解するのを手伝ってくれる人はいますか?

2 つのブランチがmasterありfooます。削除したい単一のファイルでコミットBを作成し、このファイルを変更した場所でコミットCを作成しました。他のコミットに沿って、私はこのファイルに二度と触れませんでした。

コミット ID:

A: f0e0796
B: 5ccb371
C: a46df1c
D: 8eb025b
E: b763a46
1: f5b0116
2: 175e01f

だから私はBCrebase -i f0e0796を使用して削除しますよね?結果を正しく解釈すると、これが私のレポに表示されるものですが、2番目のブランチがまだリストされています。 5ccb371 a46df1cgitkgit branches

---A-----1----2---E------> (master)

ここで何が起こったのか誰か教えてくれませんか?

編集: これは、最初のグラフからレポを再作成する方法です。

git init foo
cd foo

touch A
git add A
git commit -m "add A"

touch B
git add B
git commit -m "add B"

echo "modify" > B
git add B
git commit -m "modify B"

touch C
git add C
git commit -m "add C"

git checkout -b foo

touch 1
git add 1
git commit -m "add 1"

touch 2
git add 2
git commit -m "add 2"

git switch master
git merge foo --no-ff

touch E
git add E
git commit -m "add E"
4

5 に答える 5

2

私が提案していることは、クリーンで直線的な履歴を提供します。それが、リベースが本来行うべきことです。ただし、これにより、コミット履歴から B と B' を削除する方法が得られることを願っています。説明は次のとおりです。

Repo recreation output:
---A----B-----B'-----C--------D-------> (master)
                      \      /
                       1----2 (foo)

git log --graph --all --oneline --decorate #initial view the git commit graph
* dfa0f63 (HEAD -> master) add E
*   843612e Merge branch 'foo'
|\  
| * 3fd261f (foo) add 2
| * ed338bb add 1
|/  
* bf79650 add C
* ff94039 modify B
* 583110a add B
* cd8f6cd add A

git rebase -i HEAD~5 #here you drop 583110a/add B and ff94039/modify B from
foo branch.

git log --graph --all --oneline --decorate
$ git rebase -i HEAD~5
* 701d9e7 (HEAD -> master) add E
* 5a4be4f add 2
* 75b43d5 add 1
* 151742d add C
| * 3fd261f (foo) add 2
| * ed338bb add 1
| * bf79650 add C
| * ff94039 modify B
| * 583110a add B
|/  
* cd8f6cd add A

$ git rebase -i master foo #drop 583110a/add B and ff94039/modify B again

$ git log --graph --all --oneline --decorate #view the git commit graph

* 701d9e7 (HEAD -> foo, master) add E
* 5a4be4f add 2
* 75b43d5 add 1
* 151742d add C
* cd8f6cd add A

最後に、最終的なアウトは、A--C--1---2---E のように予想した順序ではない可能性があります。ただし、インタラクティブ モード内で順序を再度並べ替えることができます。git rebase -i HEAD~n を試してください。

注:コミット/公開履歴を変更しないことをお勧めします。私は初心者で、git を探索しています。うまくいけば、上記の解決策が定着するはずです。そうは言っても、オンラインで利用できる他の簡単なソリューションがたくさんあることは確かです. この記事は非常に役に立ちました。今後の参考のために。

于 2020-04-12T18:50:39.290 に答える
1

コミット履歴を再配置するには、いくつかの方法があります。

rebaseリポジトリ全体の履歴を変更したい場合の問題は、一度に 1 つのブランチしか移動しないことです。さらに、マージの処理に問題があるため、現在存在する最新の履歴を保持しながら単純にリベースDおよびEオンにすることはできません(マージであるため)。AE

これらすべてを回避することはできますが、その方法は複雑でエラーが発生しやすいものです。完全なレポの書き換え用に設計されたツールがあります。filter-repo(を置き換えるツール)を見たいと思うかもしれませんがfilter-branch、履歴から特定のファイルをスクラブしようとしているように思えます。これは(1)BFG Repo Cleanerに適しているか、または(2)実際には十分に簡単な作業ですfilter-branch

(BFG を調べたい場合はhttps://rtyley.github.io/bfg-repo-cleaner/ ; を調べたい場合filter-repohttps://github.com/newren/git-filter-repo )

filter-branchこの目的のために使用するには

git filter-branch --index-filter 'git rm --cached --ignore-unmatch path/to/file' --prune-empty -- --all

ただし、ファイルをリポジトリに入れないようにする必要があることを示しました(次のコミットからファイルを削除するという誰かの提案に対するカウンターとして)。したがって、git はそれほど簡単に情報を提供しないことを理解する必要があります。これらの手法のいずれかを使用した後でも、リポジトリからファイルを抽出できます。

これは一種の大きなトピックであり、SO に関するさまざまな質問/回答で何度も議論されてきたので、本当に質問する必要があることを検索することをお勧めします。コントロール。

いくつかのメモ:

1 - パスワードがあり、それらが共有リモートにプッシュされたことがある場合、それらのパスワードは危険にさらされています。それについてあなたができることは何もありません。パスワードを変更します。

2 - 各レポ (リモートおよびすべてのクローン) は、意図的にスクラブするか、破棄して置き換える必要があります。(相手が協力したくないのに強制できないことも、(1)の理由の一つです。)

3 - 修復を行ったローカル リポジトリで、reflog を削除し (および のようなツールを使用した場合に作成された可能性のあるバックアップ ref もfilter-branch)、実行する必要がありますgc。または、ブランチの新しいバージョンのみを取得する新しいリポジトリに再クローンする方が簡単な場合があります。

4 - リモートのホスト方法によっては、リモートをクリーンアップすることさえできない場合があります。場合によっては、リモートを核攻撃してから、最初から再作成することが最善の方法です。

于 2020-04-11T18:29:46.680 に答える