關於 Git 可以參考我的 Git 版本控制 課程資料
可以進一步參考 Git rebase 和 merge 合併操作示範錄影
git pull 預設的行為是將遠端的 repo. 與本地的 repo. 合併,這也是 DVCS 的初衷,將兩個 branch 合併。但是,很多時候會發生以下這種情形:
這是因為,我們團隊的開發模式是本地的 branch 和遠端的 branch 會同步地非常頻繁(通常就是同名稱的 branch,例如 master),這兩個 branch 幾乎是完全同步。這時候就會發現這些 merge 動作其實沒有必要,會造成線圖無謂的複雜。這時候,會推薦使用以下這個指令:
git pull --rebase
加上 rebase 的意思是,會先 1.把本地 repo. 從上次 pull 之後的變更暫存起來 2. 回復到上次 pull 時的情況 3. 套用遠端的變更 4. 最後再套用剛暫存下來的本地變更。詳細說明可以參考 pull with rebase。
畫圖說明一下好了:
假設合併前是這樣:
D---E master / A---B---C---F origin/master
使用 merge 合併後:
D--------E / \ A---B---C---F----G master, origin/master
如果是 rebase 的方式,就不會有 G 合併點:
A---B---C---F---D'---E' master, origin/master
注意到,其中 D’, E’ 的 commit SHA 序號跟本來 D, E 是不同的,因為算是砍掉重新 commit 了。
你會問說,有 conflict 怎麼辦? rebase 跟 merge 類似,出現 conflict 一會暫停 rebase 動作,需要你手動修復後,然後才可以繼續動作。這也是 rebase 比 merge 複雜一點的地方:merge 如果發生 conflict,你只需要解決衝突一次,然後 commit 出去就完成了。而 rebase 的 conflict 可能會發生在上述步驟 4 的每一次重新套用上,所以可能需要解決衝突好幾次 (rebase 時所謂的解決衝突,其實是直接修改你之前的變更內容,所以上圖中變成 D’ 跟 E’ )。
所以到底何時該用 merge? 何時可以 rebase? 你可能心理也有答案了,如果你修改比較多,預期會有較多的 conflict,建議用 merge (不過,如果是多次大範圍的主題式修改,那是不是應該一開始就多開一個 branch 來做呢?)。如果修改範圍較小,不太預期有 conflict,則建議可以加上 rebase 參數。
如果想要把 rebase 當做 git pull 的預設值,可以在專案的 .git/config 加上
[branch "master"]
remote = origin
merge = refs/heads/master
rebase = true
也可以直接加到 ~/.gitconfig 讓所有的 tracked branches 都自動套用這個設定:
[branch]
autosetuprebase = always
您好!
我想請教一下:
我在遠端開一個 Repository,建一個檔案叫 a,裡面寫「hi」
在遠端完成 git commit -a -m ‘say hi’
我在本機 git clone 這個 Repository 回來,修改 a 的內容為「hello」
在本機完成 git commit -a -m ‘say hello’
當我在本機執行 git push,想要將修改後的 a 推回去 origin 時,它阻止了我。
它請我在 origin 那邊的設定檔裡設定一個叫 receive.denyCurrentBranch 的變數為 ignore 或 warn。
最後印出這行:
! [remote rejected] master -> master (branch is currently checked out)
我只是很單純的想要做像 SVN 那樣的動作:
1] checkout 遠端的檔案回來
2] 本機修改完成
3] 本機 update 一下,看有沒有別人已經進行了修改
4] commit 回遠端
請問該怎麼做? =..=
萬分感謝!
oh! 我明明有排版的說 …
對了,我有試著在 origin 那邊的 config 加入那個參數,在 [core] 底下。
它說這是錯誤的,那個參數我貼上去的時候,它也沒有變特殊顏色 …
一般流程是這樣:
1] git pull
2] git commit
3] git pull
4] git push
我沒看過需要 denyCurrentBranch 的設定,google 了一下 branch is currently checked out 這個錯誤訊息似乎是你遠端 repo. 不是 bare repo.。建議你先用 github.com 練習,會了基本操作之後再學怎麼架 git server 吧。
ok! 多謝!
請教一下已經 push 到 github 上面的 commit 要如何取消呢(有 4 個 commit )?我只想要有 1 個。
一開始是這樣的,我做完事,add && commit, push 的時候說需要 pull,就 pull 下來,解決 conflict,要推的時候說我剛剛解決 conflict 沒 commit,於是又 add && commit,就變成兩個 commit 在 github 上面,我試過 git reset HEAD^ –soft 2次,然後再 commit,結果上面變成 4 個 commit 了…..
感恩
Juanito :
git push -f 會強制覆蓋掉遠端的 repository。不過如果是團隊開發,最好盡量避免。因為如果你的同事已經 pull 並且又有新的 commit,你會害到他 XD
XD! 用了一個最笨的方法解決了(複製、坐時光機*4 rest –soft、push -f)有空再來研究 rebase,感謝提點。
您好,您上面所說到git push -f 會強制覆蓋掉遠端的 repository,可是我現在遇到了問題。
我安裝git server在linux上,client端是windows,當我要上傳檔案上去時,即使遠端的REPO的檔案跟我的已經不同步,但我git push origin hotfix時,卻一直把遠端裡的檔案覆蓋掉,請問這是甚麼情形呢? 謝謝你~~^^
找到 stackoverflow.com/questions/10881978/git-push-force-by-default 也許就是你的問題。看看你專案下的 .git/config 是不是也有 push = +refs/heads/*:refs/heads/* 這行,有的話移除掉吧。
謝謝你的幫忙! 崇拜~~
想要問一下,我今天有兩隻branch
一個branch是開發機上面 dev
一個branch是線上空間 online
兩個branch的差異是設定檔
但是想把後來dev寫的commit
merge進online的branch
又不能蓋掉設定檔
應該怎麼做呢??
我还是没有理解rebase
新的code一直被同伴的舊code覆蓋,是不是因為沒rebase的關係?
不是,叫你同事不要 force push 啊
請問
git pull –rebase 如果分解動作的話是不是就是 git fetch origin master + git rebase origin/master 呢?
是的
你好 請問一下 rebase 那張圖是否有誤
順序是否應該是
A—B—D—E’—C—F’ master, origin/master
@Shaun Lin 圖沒錯喔,的確是 D, E 接到 A-B-C-F 的後面。rebase 不會受到本來 commit 時間的影響,就算 D, E 當初 commit 的時間早於 C,F,rebase master 之後還是會接到 C-F 的後面。