git pull --rebase的正確使用

文章鏈接:https://juejin.im/post/5d3685146fb9a07ed064f11b
在多人使用同一個遠程分支合作開發(fā)的時候,很可能出現(xiàn) push 代碼的時候出現(xiàn)以下問題:

$ git push origin master

# 結果如下
To github.com:hello/demo.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:hello/demo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

很明顯此時遠程分支有新的 commit 未同步到本地,無法推送。正常情況下我們會執(zhí)行以下操作:

$ git pull origin master

# 結果如下
remote: Counting objects: 2, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (2/2), done.
From github.com:hello/demo
   3824da0..f318a05  master     -> origin/master
Merge made by the 'recursive' strategy.
 one.md | 2 ++
 1 file changed, 2 insertions(+)
 
$ git push origin master

# 結果如下
Enumerating objects: 10, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 1.24 KiB | 1.24 MiB/s, done.
Total 8 (delta 5), reused 0 (delta 0)
To github.com:hello/demo.git
   f318a05..1aefef1  master -> master

確實 push 成功了,但是此時用 git log 查看以下提交記錄:

$ git log

# 結果如下
commit 1aefef1a2bedbd3ebd82db8dcf802011a35a9888 (HEAD -> master, origin/master, origin/HEAD)
Merge: 24cfa5c f318a05
Author: hello <hello@qq.com>
Date:   Tue Jul 23 09:53:47 2019 +0800

    Merge branch 'master' of github.com:hello/demo

commit 24cfa5c3ad271e85ff0e64793bf2bcc9d700c233
Author: hello <hello@qq.com>
Date:   Tue Jul 23 09:50:06 2019 +0800

    feat: 新功能提交

commit f318a05b1a4cbc0a6cf8d7dc7d3fb99cbafb0363
Author: world <world@qq.com>
Date:   Tue Jul 23 09:48:20 2019 +0800

    feat: 其他功能提交

...

你會發(fā)現(xiàn)多出了一條 merge commit,這個 commit 就是在執(zhí)行 git pull origin master 的時候自動生成的。如果多人多次如此操作,那么提交記錄就會出現(xiàn)很多條這種自從生成的 merge commit,非常難看。
要解決以上問題,不再出現(xiàn)自動生成的 merge commit,那么只要在執(zhí)行 git pull origin master 的時候帶上 --rebase 即可:

$ git pull --rebase origin master

$ git push origin master

項目示例

現(xiàn)在通過一個示例項目來示范以上命令的用法。項目(demo)的結構如下:

# 在 demo 目錄下執(zhí)行以下命令

$ ls

# 結果如下
one.md  two.md

$ cat one.md

# 結果如下
hello one

$ cat two.md

#結果如下
hello two

A、B兩位開發(fā)同學使用一個遠程分支(master)合作開發(fā)。A同學修改了 one.md 文件,提交了一個 commit 并且已經(jīng)推送到遠程分支 master:

$ cat one.md

# 結果如下
hello one

new feature for one

$ git push origin master

# 結果如下
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 1.24 KiB | 1.24 MiB/s, done.
Total 4 (delta 3), reused 0 (delta 0)
To github.com:hello/demo.git
   f318a05..1aefef1  master -> master

此時B同學不知情,也并未將遠程分支的更新拉到本地。B同學修改了 two.md 文件,也提交了一個 commit 并嘗試推送到遠程分支 master:

$ cat two.md

# 結果如下
hello two

new feature for two

$ git push origin master

# 結果如下
To github.com:hello/demo.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:hello/demo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

發(fā)現(xiàn)報錯,無法推送。此時執(zhí)行以下命令:

$ git pull --rebase

$ git push origin master

即可成功推送。

注意事項

  • 執(zhí)行 git pull --rebase的時候必須保持本地目錄干凈。 即:不能存在狀態(tài)為 modified 的文件。(存在Untracked files是沒關系的)
  • 如果出現(xiàn)沖突,可以選擇手動解決沖突后繼續(xù)rebase,也可以放棄本次rebase

執(zhí)行 git pull --rebase 的時候必須保持本地目錄干凈

1. 有 modified 狀態(tài)的文件

本地有受版本控制的文件改動的時候,執(zhí)行以上命令:

$ git pull --rebase

# 結果如下
error: cannot pull with rebase: You have unstaged changes.
error: please commit or stash them.

會出現(xiàn)以上報錯,無法操作。

此時查看以下文件狀態(tài):

$ git status

# 結果如下
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   two.md

no changes added to commit (use "git add" and/or "git commit -a")

就是因為本地有文件改動尚未提交造成的。此時有兩種做法:

  • 如果本次修改已經(jīng)完成,則可以先提交(commit)一下
  • 如果本次修改尚未完成,則可以先貯藏:git stash

做了以上一種操作之后再嘗試 git pull --rebase,不會再報錯。
如果做了 git stash 操作,此時可以通過 git stash pop 回到之前的工作狀態(tài)。

Untracked files

查看本地文件狀態(tài):

$ git status

# 結果如下
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    three.md

no changes added to commit (use "git add" and/or "git commit -a")

如果是以上這種情況,直接執(zhí)行 git pull --rebase 是不會有問題的。

如果出現(xiàn)沖突,可以選擇手動解決沖突后繼續(xù) rebase,也可以放棄本次 rebase

在上面的示例項目中,如果 A、B 同學修改了同一個文件。那么很有可能會出現(xiàn)沖突,當 B 同學來執(zhí)行命令的時候會出現(xiàn)如下狀況:

$ git pull --rebase

# 結果如下
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From gitlab.lrts.me:fed/gitlab-merge
   93a1a93..960b5fc  master     -> origin/master
First, rewinding head to replay your work on top of it...
Applying: feat: 其他功能提交
Using index info to reconstruct a base tree...
M   one.md
Falling back to patching base and 3-way merge...
Auto-merging one.md
CONFLICT (content): Merge conflict in one.md
error: Failed to merge in the changes.
Patch failed at 0001 feat:其他功能提交
hint: Use 'git am --show-current-patch' to see the failed patch

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

這種情況下,可以手動打開 one.md 文件解決沖突,然后再執(zhí)行:

$ git add one.md

$ git rebase --continue

解決問題。

也可以用 git rebase --abort 放棄本次 rebase 操作。

總結

多人基于同一個遠程分支開發(fā)的時候,如果想要順利 push 又不自動生成 merge commit,建議在每次提交都按照如下順序操作:

$ git stash

$ git pull --rebase

$ git push

$ git stash pop
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • git 使用筆記 git原理: 文件(blob)對象,樹(tree)對象,提交(commit)對象 tree對象 ...
    神刀閱讀 3,849評論 0 10
  • 1. GIT命令 git init在本地新建一個repo,進入一個項目目錄,執(zhí)行git init,會初始化一個re...
    江邊一蓑煙閱讀 889評論 0 0
  • 使用Git已有很長一段時間,遇到一些痛點問題,而且大都是網(wǎng)上難以直接查到的,故總結于此。 1.兩幅重要的圖 以上兩...
    承羿閱讀 2,174評論 0 8
  • 肉肉的海參 天氣轉涼,是養(yǎng)心安神的好季節(jié),今日推薦兩道菜,烏龍吐珠、蓮藕排骨湯。 【烏龍吐珠】 烏龍吐珠 原料:水...
    金秒學堂閱讀 397評論 0 0
  • 被利用,說明你還有可用之處。 人是社群動物,人和人都是相互依存的。所謂的商業(yè)文明,說到底是因交換而存在而繁盛。交換...
    縱衡閱讀 200評論 0 0

友情鏈接更多精彩內容