與遠端倉庫保持同步

moduzhang發表於2018-08-30

建立 Pull Request

Pull Request拉取請求)是向初始源倉庫的維護者發出的請求,以讓其將你在他們專案的 fork 上所做的更改應用在他們的專案中。你請求他們拉取你做的更改。你需要完成一些操作:

  • 你必須 fork 源倉庫
  • 將你的 fork 克隆到你的計算機
  • 進行一些 commit(最好是在特性分支上!)
  • 將 commit 推送回你的 fork
  • 建立一個新的 Pull Request,並選擇包含你的新 commit 的分支

Pull Request 操作過程

一個屬於其它開發者的倉庫,我們決定 fork 它,建立的是完全相同的副本,因此這兩個倉庫(OriginalForked)將具有完全相同的 commit,它們的分支也會指向相同的 commit。

這裡寫圖片描述

要建立 Pull Request 我們需要在我們的 fork 副本中新增新的 commit,因此將我們的 fork 副本克隆到本地機器上。

這裡寫圖片描述

我們建立一個 BUGFIX 分支並提交幾個 commit 來修復錯誤,然後將 BUGFIX 分支推送到我們的 fork 副本上,以讓這些新的 commit 出現在遠端倉庫上。我們通過更改推送至我們的 fork 副本上,做好了 Pull Request 的所有準備工作。

這裡寫圖片描述

現在我們將真正建立 Pull Request,稍後說明如何在 GitHub 上執行這一操作。如果 Pull request 被原始倉庫的維護者接受了,commit 將被新增到他們的倉庫中。建立一個合併 commit 以將我們的新 commit 與他們的現有 commit 合併。他們的 master 分支將使指標移動到這個新的合併 commit 上。

這裡寫圖片描述

建立 Pull request 過程

這時我想把我對這個專案的更改新增到她的專案中,就需要使用 pull request(拉取請求)功能,點選 GitHub fork 的倉庫的頁面,點選 New pull request 按鈕,傳送一個新的 pull request。這裡顯示的是比較我的專案倉庫中的 master 分支和原專案倉庫中的 master 分支,我們切換我們剛剛推送上來的新特性分支,頁面發生了變化,下面會列出 原 master 分支和我的特性分支之間的差異。檢視完整後,點選 Create pull request 按鈕,跳轉到實際傳送 pull request 的地方,填寫完標題和描述資訊後點選 Create pull request。頁面會跳轉到原倉庫 Pull request 頁面檢視我們剛才建立的 Pull request 的內容,但是已經不能修改,需要原倉庫作者來判斷,是否需要將 pull request 中的更改加到他的 master 分支上。

Star 和 Watch

Star 是能幫助你跟蹤感興趣倉庫的一個有用功能,同時也成為了衡量倉庫受歡迎程度的手段。

如果你要跟進一個專案的變化,並希望接收變更通知,GitHub 為你提供了 “Watch” 功能。如果你頻繁地在一個倉庫上工作,那麼我建議你將 watch 設定改為”Watching“(持續關注)。這樣,當該倉庫發生任何活動時,GitHub 都會通知你,例如當有人向倉庫推送變更,建立了新的 Issues,或者在現有 Issues 中新增了評論。

當有一些 commit 被推送到了初始源倉庫。你如何讓這些更改進入你 fork 的倉庫副本中?如果你想繼續在你的 fork 上進行開發,那麼就需要讓你 fork 的副本儘可能與源倉庫保持同步

在我的本地倉庫中,我已經有一個遠端倉庫了,那就是 origin

這裡寫圖片描述

注意 origin 一詞只是第一次 git clone 遠端倉庫時使用的預設名稱。我們將使用 git remote 命令來向此列表新增一個新的簡寫名和 URL。這會提供給我們一個與源倉庫之間的連線。

$ git remote add upstream https://github.com/udacity/course-collaboration-travel-plans.git

我們來看看在新增了新的遠端倉庫後,遠端倉庫的列表現在是什麼樣的:

這裡寫圖片描述

現在,要獲得上游遠端倉庫的更改,我們只需執行 git pull 並使用 upstream 簡寫名,而不是 origin 簡寫名:

$ git pull upstream master

這裡寫圖片描述

一個新的分支新增到了本地。

$ git log --oneline --graph --decorate --all

這裡寫圖片描述

現在本地 master 分支前有一個 upstream/master 遠端分支。我們不想執行 git push origin upstream/master,因為 upstream/master 不是本地分支。要將這些更改融入我 fork 的她的專案版本,我可以將 upstream/master 合併到一個現有分支中(例如本地 master 分支)然後推送它。

# 確保我位於正確的合併分支上
$ git checkout master

# 合併 Lam 的更改
$ git merge upstream/master

# 將 Lam 的更改傳送到*我的*遠端倉庫
$ git push origin master

要將源倉庫的更改提取到你在 GitHub 上 fork 的倉庫副本,你需要:

  • 獲得源倉庫的可克隆 URL
  • 使用 git remote add 命令建立一個新的遠端倉庫,使用簡寫名 upstream 指向源倉庫,提供源倉庫的 URL
  • 獲取新的 upstream 遠端倉庫
  • upstream 的分支合併到本地分支
  • 將新更新的本地分支推送到你的 origin 倉庫

如果專案維護者要求更改 Pull Request,則:

  • 在你的 Pull Request 所基於的本地倉庫的同一分支上新增一些必要 commit
  • 將該分支推送到你的源倉庫 fork 副本

這些 commit 最終將顯示在 Pull Request 頁面上。

壓制 commit

要將 commit 壓制在一起,我們要使用非常強大的 git rebase 命令。

壓制的工作原理

這裡寫圖片描述

我們可以執行 git rebase -i HEAD~3,將最後三個 commit 合併或壓制成一個 commit,注意 HEAD 指向當前的位置。

這裡寫圖片描述

我們位於 master 分支上,因此 HEAD 指向 master 分支。執行後會建立一個新的 commit SHA,並移動 master 分支使其指向新的 commit,但是注意沒有分支指向原始 commit,git 最終將完全清除它們。

這裡寫圖片描述

如果擔心損壞倉庫並想要備份下,那麼在使用 git rebase 時,先建立一個 backup 的分支,將其放在和要 rebase 的分支所在的位置相同的位置。

這裡寫圖片描述

我依然在 master 分支上,沒有切換到 backup 分支,接著執行之前的壓制命令,這樣使多個 commit 壓制為一個,並使 master 指向這個新的 commit。但原來 commit 沒有被刪除,且依然會顯示在 git log 輸出結果中,因為 backup 分支指向了它們。

rebase 命令

git rebase 命令會將 commit 移動到一個新基底(base)上。命令中的 -i 代表”互動式“。你可以在非互動模式下執行 rebase。在你學習如何 rebase 時,我明確建議你進行互動式 rebase。

  • 使用 ppick – 使 commit 保持原樣
  • 使用 rreword – 保留 commit 的內容,但修改 commit 說明
  • 使用 eedit – 保留 commit 的內容,但先不要執行 commit,以便新增新內容或檔案、刪除內容或檔案、修改即將 commit 的內容
  • 使用 ssquash – 將此 commit 的更改結合到之前的 commit 中(列表中位於其上面的 commit )
  • 使用 ffixup – 將此 commit 的更改結合到前一個 commit 中,但刪除提交說明
  • 使用 xexec – 執行 shell 命令
  • 使用 ddrop – 刪除 commit

強制推送

使用 git rebase 會建立一個具有新 SHA 的新 commit。當我嘗試使用 git push 將此 commit 推送至 GitHub 時,GitHub 知道接受此推送會刪除那三個單獨 commit,所以它拒絕了。因此,我不得不使用 git push -f 強制推送這些 commit。

何時變基

git rebase 命令非常強大。它可以幫助你編輯提交說明、重新排序 commit、合併 commit 等,真的是一款非常強大的工具。現在的問題是”應該何時進行變基?

每當你對 commit 進行變基,Git 將為每個 commit 建立一個新的 SHA!這有很大的影響。對於 Git,SHA 為 commit 的識別符號,因此不同的識別符號代表著不同的 commit,無論內容是否發生了變化。

如果你已推送了你想進行變基的 commit,則不應變基。如果你在與其他開發者協作,那麼他們可能已經在使用你推送的 commit。如果你隨後使用 git rebase 來進行更改,並強行推送 commit,則其他開發者現在將無法與遠端倉庫同步。他們需要對自己的 Git 倉庫進行一些複雜的手術,使它們的倉庫回到工作狀態……甚至可能連這一點都做不了;他們可能得拋棄之前的所有工作,使用你新變基過且強制推送的 commit 重新開始。

Git 分支 - 變基
git-rebase Git 文件

總結

  • 如何設定遠端倉庫
  • 如何將更改推送到遠端倉庫並從中獲取更改
  • 如何 fork 倉庫
  • 開始處理新功能或專案更改前,要採取的初步步驟
  • 如何建立 Pull Request
  • 瞭解與專案其他利益相關者清楚、頻繁溝通的重要性

Git Community Book 中文版
git-tips

相關文章