這是我本地 Git 存盤庫的結構。可以看出,分支master和remotes/tpt3/master之間存在不連續性和差距。但是必須只有 1 個連續分支,以便master的提交應該在remotes/tpt3/master的最后一次提交之后進行,并且只有 1 個分支必須包含所有這些提交。
當我嘗試使用命令時:
$git rebase --onto remotes/tpt3/master master
它導致以下錯誤結果。
首先,master應該在remotes/tpt3/master 之后。其次,master的提交在某處消失了。
你能告訴我應該使用哪個 Git 命令從master和remotes/tpt3/master創建一個連續的分支嗎?
uj5u.com熱心網友回復:
前注:您將在此處使用的命令是:
git add # insert arguments as needed here
git commit
git replace --graft master~2 tpt3/master
(在此處檢查結果以確保一切正常)
git filter-branch -- master
(再次檢查結果)
git for-each-ref --format="%(refname)" refs/original | xargs git update-ref -d
(再次檢查),以及:
git reset HEAD~
F'從master(見下文)中洗掉提交,然后git push tpt3 master.
在做任何事情之前仔細閱讀以下內容,并考慮在開始之前備份您的存盤庫!
旁注:gitk是一個有用的(雖然不是很好)提交查看器,但gitk影像對于 StackOverflow 上的問題來說很糟糕。我在這里重新輸入了第一張圖片中的一些關鍵部分,盡管我可能插入了任意數量的印刷錯誤:
- Local uncommitted changes, not checked in to index
* (master) Commit 22.10.21. Just verified Fe-Fe nuc...
* Initial commit.t Np=100100000 TITAN YEILD COUNT=9...
* (remotes/tpt3/master) After quarantine. STEP #29
* After Quarantine. STEP #28
* After Quarantine. STEP #27
這表示總共五個提交,在兩個單獨(不相交)的 DAG 中。兩個圖表中的每一個都包含以線性方式排列的兩個或三個提交。(注意:第二張圖片顯示第一張圖片是謊言,所以請注意:我正在從謊言中作業。您需要將自己的大腦應用于以下內容。)
如果我們為每個提交分配字母代碼,并且如果我們將未提交的作業放入當前分支的第三次提交中,我們將得到:
F: Local uncommitted changes, not checked in to index
E: (master) Commit 22.10.21. Just verified Fe-Fe nuc...
D: Initial commit.t Np=100100000 TITAN YEIDL COUNT=9...
C: (remotes/tpt3/master) After quarantine. STEP #29
B: After Quarantine. STEP #28
A: After Quarantine. STEP #27
兩個提交圖是:
A <-B <-C <-- remotes/tpt3/master
D <-E <-F <-- master
似乎您想要:
A <-B <-C <-- remotes/tpt3/master
\
D <-E <-F <-- master
您不能完全理解這一點,因為提交D并且E已經存在,因此無法更改,但是它們可以被復制到新的改進提交中,否則它們非常相似D和E。(提交F實際上還不存在,但您需要制作它,以保存作業樹的內容,除非您在單獨的克隆或添加的作業樹中完成所有作業,這兩者都沒有太大好處:只需提交F然后我們將以與D和相同的方式復制它E。然后,您可以使用 將提交(F'復制)從鏈的末端引導,同時將作業保留在您的作業樹中git reset。)
You can almost, but not quite, make the new improved commits using git rebase. You tried this already but used the wrong command:
$git rebase --onto remotes/tpt3/master master
What git rebase does can be thought of as (and depending on your Git version, now is, or else approximates) repeated cherry-picking. Each cherry-pick operation copies one commit. The crucial parts of this process are:
git rebasemust list out all the commits to copy. This is where your incorrect arguments are biting you now, as Leonardo Alves Machado commented. Runninggit rebase --onto remotes/tpt3/masterrequires that you then list which commits not to copy from the current branch; you say do not copy any commits up to and including the latest one onmaster, which results in copying no commits. Fixing this—by usinggit rebase remotes/tpt3/masterinstead—would attempt to cherry-pick (copy) allmaster-branch commits, which is much closer to what you want. It still won't quite work—probably—because of step 3 below.The rebase code now does a detached HEAD style checkout or switch to the target (
--ontoor otherwise specified) commit. In this case you want to use theremotes/tpt3/mastercommit,After quarantine. STEP #29.The rebase code now repeatedly runs
git cherry-pickor equivalent. Each cherry-pick turns a commit into a change-set, and then copies that change-set atop the current commit and commits the result. For two of the three to-be-copied commits,EandF, this is the correct action. However, commitDhas no parent, so cherry-pick will simply consider each file in commitDas added-from-scratch. This is likely to cause a big mess of add/add conflicts: each "copy" step is actually a three-way merge and this merge is likely to go wrong here.Last, having copied all the commits,
git rebasewrests the branch name of the branch you were on before step 2 so that it now points to the current commit, which is the last-copied commit or—in your case where you copied no commits—the commit Git checked out in step 2.
The cure for this particular problem—where step 3 thinks of every commit as an add/add conflict-is probably to use git replace to make a graft that makes Git pretend that commit D has commit C as a parent. Once the graft is in place, you have:
A--B--C <-- remotes/tpt3/master
:
D--E--F <-- master
This sort of vague pretend link won't quite do the job, but using git filter-branch or the new git filter-repo can then "cement the graph into place" by replacing commits D, E, and F with new commits D', E', and F' that—except for having different hash IDs themselves1 and referring back to C, D', and E' respectively—are otherwise identical to D, E, and F: they have the same snapshot, and mostly the same metadata. That is, post-filter-branch / filter-repo, you now have:
A--B--C <-- remotes/tpt3/master
\
D'-E'-F' <-- master
which is what you want. You can now run git push tpt3 master safely; this will add on the three commits.
因為你很可能只是想兩次提交未提交加的變化,我們現在可以使用git reset踢提交F'關閉master。請注意,提交F'會在您的存盤庫中繼續存在D-E-F一段時間(就像 commits 一樣),但是沒有簡單的方法可以找到提交,您將看不到它們。就好像它們從未存在過一樣。最終——在 30 天或更長時間后——Git 會注意到它們沒有被使用并真正丟棄它們。
所以,此時你只需運行:
git reset HEAD~
告訴 Git:
- 將當前分支名稱后移一級;
- 也重置它的索引,但保持你的作業樹不變。
您現在將擁有:
A--B--C <-- remotes/tpt3/master
\
D'-E' <-- master
與未完成的作業,如您所愿。
1由于提交哈希 ID是提交的真實名稱,因此這意味著D'完全不同于D,例如。它們具有相同的快照和大部分相同的元資料這一事實對 Git 不感興趣——至少在這個級別不是——因為 Git 只關心這個級別的哈希 ID。所以這有點像那個老笑話,“除此之外,林肯夫人,這出戲怎么樣?” ——除非在這種情況下,Abe 被一個沒有人(可能除了林肯夫人)能發現的克隆人所取代。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/398258.html
