簡體   English   中英

如何更新或同步 GitHub 上的分叉存儲庫?

[英]How do I update or sync a forked repository on GitHub?

我分叉了一個項目,進行了更改,並創建了一個被接受的拉取請求。 新的提交后來被添加到存儲庫中。 我如何將這些提交放入我的分叉中?

在分叉存儲庫的本地克隆中,您可以將原始 GitHub 存儲庫添加為“遠程”。 (“遠程”就像存儲庫 URL 的昵稱 - 例如, origin是其中之一。)然后您可以從該上游存儲庫中獲取所有分支,並重新調整您的工作以繼續處理上游版本。 就可能看起來像這樣的命令而言:

# Add the remote, call it "upstream":

git remote add upstream https://github.com/whoever/whatever.git

# Fetch all the branches of that remote into remote-tracking branches

git fetch upstream

# Make sure that you're on your master branch:

git checkout master

# Rewrite your master branch so that any commits of yours that
# aren't already in upstream/master are replayed on top of that
# other branch:

git rebase upstream/master

如果您不想重寫 master 分支的歷史記錄(例如,因為其他人可能已經克隆了它),那么您應該將最后一個命令替換為git merge upstream/master 但是,為了進一步提出盡可能干凈的拉取請求,最好重新設置基准。


如果您已將分支重新定位到upstream/master上,您可能需要強制推送以便將其推送到您自己在 GitHub 上的分叉存儲庫。 你會這樣做:

git push -f origin master

您只需要在重新定位后第一次使用-f即可。

從 2014 年 5 月開始,可以直接從 GitHub 更新分叉。 這在 2017 年 9 月仍然有效,它會導致一個骯臟的提交歷史。

  1. 在 GitHub 上打開你的 fork。
  2. 單擊拉取請求
  3. 單擊新的拉取請求 默認情況下,GitHub 會將原始版本與您的 fork 進行比較,如果您未進行任何更改,則不應有任何可比較的內容。
  4. 如果您看到該鏈接,請單擊切換基礎 否則,手動將基叉下拉設置為您的前叉,將頭叉設置為上游。 現在 GitHub 會將您的 fork 與原始版本進行比較,您應該會看到所有最新的更改。 在此處輸入圖像描述
  5. 創建拉取請求並為您的拉取請求分配一個可預測的名稱(例如, Update from original )。
  6. 向下滾動到Merge pull request ,但不要單擊任何內容。

現在您有三個選項,但每個選項都會導致提交歷史不太干凈。

  1. 默認將創建一個丑陋的合並提交。
  2. 如果您單擊下拉菜單並選擇“壓縮並合並”,則所有介入的提交都將被壓縮為一個。 這通常是您不想要的。
  3. 如果你點擊Rebase and merge ,所有的提交都會和你一起進行,原來的 PR 會鏈接到你的 PR,GitHub 會顯示This branch is X commits ahead, Y commits behind <original fork>

所以是的,你可以使用 GitHub Web UI 讓你的 repo 更新到它的上游,但是這樣做會破壞你的提交歷史。 改用命令行- 這很容易。

這是 GitHub 關於Syncing a fork的官方文檔:

同步分叉

設置

在同步之前,您需要添加一個指向上游存儲庫的遠程。 當你最初分叉時,你可能已經這樣做了。

提示:同步你的 fork 只會更新你的本地倉庫副本; 它不會更新您在 GitHub 上的存儲庫。

 $ git remote -v # List the current remotes origin https://github.com/user/repo.git (fetch) origin https://github.com/user/repo.git (push) $ git remote add upstream https://github.com/otheruser/repo.git # Set a new remote $ git remote -v # Verify new remote origin https://github.com/user/repo.git (fetch) origin https://github.com/user/repo.git (push) upstream https://github.com/otheruser/repo.git (fetch) upstream https://github.com/otheruser/repo.git (push)

同步

將存儲庫與上游同步需要兩個步驟:首先必須從遠程獲取,然后必須將所需的分支合並到本地分支。

抓取

從遠程存儲庫中獲取將引入其分支及其各自的提交。 這些存儲在特殊分支下的本地存儲庫中。

 $ git fetch upstream # Grab the upstream remote's branches remote: Counting objects: 75, done. remote: Compressing objects: 100% (53/53), done. remote: Total 62 (delta 27), reused 44 (delta 9) Unpacking objects: 100% (62/62), done. From https://github.com/otheruser/repo * [new branch] master -> upstream/master

我們現在將上游的 master 分支存儲在本地分支 upstream/master 中

$ git branch -va # List all local and remote-tracking branches * master a422352 My local commit remotes/origin/HEAD -> origin/master remotes/origin/master a422352 My local commit remotes/upstream/master 5fdff0f Some upstream commit

合並

現在我們已經獲取了上游存儲庫,我們希望將其更改合並到我們的本地分支中。 這將使該分支與上游同步,而不會丟失我們的本地更改。

 $ git checkout master # Check out our local master branch Switched to branch 'master' $ git merge upstream/master # Merge upstream's master into our own Updating a422352..5fdff0f Fast-forward README | 9 ------- README.md | 7 ++++++ 2 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 README create mode 100644 README.md

如果您的本地分支沒有任何獨特的提交,git 將改為執行“快進”:

 $ git merge upstream/master Updating 34e91da..16c56ad Fast-forward README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)

提示:如果您想更新 GitHub 上的存儲庫,請按照此處的說明進行操作

很多答案最終會將您的 fork 移到父存儲庫之前的一個提交 此答案總結了此處找到的步驟,這些步驟會將您的 fork 移至與 parent 相同的提交

  1. 將目錄更改為您的本地存儲庫。

    • 如果你不是git checkout master切換到 master 分支
  2. 將父級添加為遠程存儲庫, git remote add upstream <repo-location>

  3. git fetch upstream
  4. 發出git rebase upstream/master

    • 在這個階段,您可以通過輸入git status檢查是否提交了將要合並的內容
  5. 發出git push origin master

有關這些命令的更多信息,請參閱步驟 3

如果像我一樣,你從不直接向 master 提交任何東西,你真的應該這樣做,你可以執行以下操作。

從 fork 的本地克隆,創建上游遠程。 你只需要這樣做一次:

git remote add upstream https://github.com/whoever/whatever.git

然后,每當您想趕上上游存儲庫主分支時,您需要:

git checkout master
git pull upstream master

假設你自己從來沒有在 master 上做過任何事情,你應該已經完成​​了。 現在,您可以將本地 master 推送到您的源遠程 GitHub 分支。 您還可以在您現在最新的本地 master 上重新設置您的開發分支。

通過初始上游設置和主節點結帳,您需要做的就是運行以下命令以將您的主節點與上游同步: git pull upstream master

前言:你的 fork 是“起源”,而你 fork 的存儲庫是“上游”。

假設您已經使用以下命令將 fork 克隆到您的計算機:

git clone git@github.com:your_name/project_name.git
cd project_name

如果給出了,那么您需要按以下順序繼續:

  1. 將“上游”添加到您的克隆存儲庫(“來源”):

     git remote add upstream git@github.com:original_author/project_name.git
  2. 從“上游”獲取提交(和分支):

     git fetch upstream
  3. 切換到 fork 的“master”分支(“origin”):

     git checkout master
  4. 存儲“master”分支的更改:

     git stash
  5. 將“上游”的“master”分支的更改合並到“origin”的“master”分支中:

     git merge upstream/master
  6. 解決合並沖突(如果有)並提交合並

    git commit -am "Merged from upstream"
  7. 將更改推送到您的 fork

     git push
  8. 取回隱藏的更改(如果有)

     git stash pop
  9. 你完成了! 恭喜!

GitHub 還提供了有關此主題的說明:同步分叉

自 2013 年 11 月以來,GitHub 收到了一個非官方的功能請求,要求他們添加一種非常簡單直觀的方法來保持本地分支與上游同步:

https://github.com/isaacs/github/issues/121

注意:由於功能請求是非官方的,因此建議您聯系support@github.com以添加您對要實現的此類功能的支持。 上面的非官方功能請求可以用作對此正在實施的興趣量的證據。

GitHub 現在推出了一項功能,只需單擊按鈕即可同步分叉

轉到您的 fork,單擊Fetch upstream ,然后單擊Fetch and merge以直接將您的 fork 與其父 repo 同步。

在此處輸入圖像描述

您也可以單擊“ Compare ”按鈕在合並之前比較更改。

參考:GitHub 的文檔

有三種方法可以做到這一點:從 Web UI(選項 1)、從 GitHub CLI(選項 2)或從命令行(選項 3)。


選項 1 - 網頁界面

  1. 在 GitHub 上,導航到要與上游存儲庫同步的分叉存儲庫的主頁。

  2. 選擇獲取上游下拉菜單。

在此處輸入圖像描述

  1. 查看來自上游存儲庫的提交的詳細信息,然后單擊 Fetch and merge。

在此處輸入圖像描述


選項 2 - GitHub CLI

要從其父分支更新遠程分支,請使用gh repo sync子命令並提供您的分支名稱作為參數。

$ gh repo sync owner/cli-fork

如果上游存儲庫的更改導致沖突,則 GitHub CLI 無法同步。 您可以設置-force標志以覆蓋目標分支。


選項 3 - 命令行

在將一個分支與上游存儲庫同步之前,必須在 Git 中配置一個指向上游存儲庫的遠程

1 打開 Git Bash。

2 將當前工作目錄更改為您的本地項目。

3 從上游存儲庫獲取分支及其各自的提交。 對 BRANCHNAME 的提交將存儲在本地分支 upstream/BRANCHNAME 中。

$ git fetch upstream
> remote: Counting objects: 75, done.
> remote: Compressing objects: 100% (53/53), done.
> remote: Total 62 (delta 27), reused 44 (delta 9)
> Unpacking objects: 100% (62/62), done.
> From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY
>  * [new branch]      main     -> upstream/main

4 檢查你的 fork 的本地默認分支 - 在這種情況下,我們使用 main。

$ git checkout main
> Switched to branch 'main'

5 將上游默認分支(在本例中為 upstream/main)中的更改合並到本地默認分支中。 這將使您的 fork 的默認分支與上游存儲庫同步,而不會丟失您的本地更改。

$ git merge upstream/main
> Updating a422352..5fdff0f
> Fast-forward
>  README                    |    9 -------
>  README.md                 |    7 ++++++
>  2 files changed, 7 insertions(+), 9 deletions(-)
>  delete mode 100644 README
>  create mode 100644 README.md

如果一個本地分支沒有任何獨特的提交,Git 將改為執行“快進”:

$ git merge upstream/main
> Updating 34e91da..16c56ad
> Fast-forward
>  README.md                 |    5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)

注意:同步一個人的分叉只會更新一個人的本地副本。 要在 GitHub.com 上更新一個分支,必須推送一個更改


來源: GitHub Docs - 同步分叉

截至本答案發布之日,GitHub 還沒有(或者我應該不再說? )Web 界面中的此功能。 但是,您可以要求support@github.com添加您的投票。

與此同時,GitHub 用戶 bardiharborow 創建了一個工具來做到這一點: https ://upriver.github.io/

來源在這里: https ://github.com/upriver/upriver.github.io

如果您使用 GitHub for Windows 或 Mac,那么現在它們具有一鍵更新 forks 的功能:

  1. 在 UI 中選擇存儲庫。
  2. 單擊頂部的“從用戶/分支更新”按鈕。

實際上,可以從瀏覽器中上游的任何提交在您的 fork 中創建一個分支:

在此處輸入圖像描述

然后,您可以將該分支獲取到您的本地克隆,當您在該提交之上推送編輯時,您不必將所有數據推送回 GitHub。 或者使用 Web 界面更改該分支中的某些內容。

它是如何工作的(這是一個猜測,我不知道 GitHub 到底是怎么做的):forks 共享對象存儲並使用命名空間來分隔用戶的引用。 因此,您可以通過您的 fork 訪問所有提交,即使它們在分叉時不存在。

請按照以下步驟操作。 我嘗試了它們,它幫助了我。

結帳到您的分行

語法: git branch yourDevelopmentBranch
示例: git checkout master

拉取源代碼庫分支以獲取最新代碼

語法: git pull https://github.com/tastejs/awesome-app-ideas master
示例: git pull https://github.com/ORIGINAL_OWNER/ORIGINAL_REPO.git BRANCH_NAME

我用這一行更新了我的分叉回購:

git pull https://github.com/forkuser/forkedrepo.git branch

如果您不想將另一個遠程端點添加到您的項目中,請使用此選項,就像此處發布的其他解決方案一樣。

作為對這個答案的補充,我正在尋找一種方法來一次從上游分支更新我克隆的 repo ( origin ) 的所有遠程分支。 我就是這樣做的。

這假設您已經配置了一個指向源存儲庫( origin從中分叉的地方)的上游遠程,並已將其與git fetch upstream同步。

然后運行:

for branch in $(git ls-remote --heads upstream|sed 's#^.*refs/heads/##'); do git push origin refs/remotes/upstream/$branch:refs/heads/$branch; done

該命令的第一部分列出了上游遠程 repo 中的所有頭,並刪除了 SHA-1,后跟refs/heads/分支名稱前綴。

然后對於這些分支中的每一個,它將上游遠程跟蹤分支的本地副本(本地端的refs/remotes/upstream/<branch> )直接推送到端的遠程分支(遠程端的refs/heads/<branch> )。

這些分支同步命令中的任何一個都可能由於以下兩個原因之一失敗:上游分支已被重寫,或者您已將該分支上的提交推送到您的 fork。 在第一種情況下,您沒有向 fork 上的分支提交任何內容,強制推送是安全的(添加-f開關;即git push -f在上面的命令中)。 在另一種情況下,這是正常的,因為您的 fork 分支已經發散,並且在您的提交合並回upstream之前,您不能期望 sync 命令起作用。

“Pull”應用程序是一種自動設置和忘記的解決方案。 它會將你的 fork 的默認分支與上游存儲庫同步。

訪問 URL,單擊綠色的“安裝”按鈕並選擇要啟用自動同步的存儲庫。

該分支每小時直接在 GitHub 上更新一次,在您的本地機器上,您需要拉取 master 分支以確保您的本地副本是同步的。

如果你設置你的上游。 檢查git remote -v ,就足夠了。

git fetch upstream
git checkout master
git merge --no-edit upstream/master
git push

克隆分叉存儲庫后,轉到克隆所在的目錄路徑和 Git Bash 終端中的幾行。

$ cd project-name

$ git remote add upstream https://github.com/user-name/project-name.git
 # Adding the upstream -> the main repo with which you wanna sync

$ git remote -v # you will see the upstream here 

$ git checkout master # see if you are already on master branch

$ git fetch upstream

你可以走了。 主存儲庫中的所有更新更改都將推送到您的 fork 存儲庫中。

“fetch”命令對於在項目中保持最新是必不可少的:只有在執行“git fetch”時,您才會被告知您的同事推送到遠程服務器的更改。

您仍然可以訪問此處進行進一步查詢

假設你的 fork 是https://github.com/me/foobar並且原始存儲庫是https://github.com/someone/foobar

  1. 訪問https://github.com/me/foobar/compare/master...someone:master

  2. 如果您看到綠色文本Able to merge然后按Create pull request

  3. 在下一頁上,滾動到頁面底部,然后單擊Merge pull requestConfirm merge

使用此代碼段生成鏈接以同步您的分叉存儲庫:

 new Vue ({ el: "#app", data: { yourFork: 'https://github.com/me/foobar', originalRepo: 'https://github.com/someone/foobar' }, computed: { syncLink: function () { const yourFork = new URL(this.yourFork).pathname.split('/') const originalRepo = new URL(this.originalRepo).pathname.split('/') if (yourFork[1] && yourFork[2] && originalRepo[1]) { return `https://github.com/${yourFork[1]}/${yourFork[2]}/compare/master...${originalRepo[1]}:master` } return 'Not enough data' } } })
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> Your fork URL: <input size=50 v-model="yourFork" /> <br /> Original repository URL: <input v-model="originalRepo" size=50 /> <br /> Link to sync your fork: <a :href="syncLink">{{syncLink}}</a> </div>

$ git remote add upstream https://github.com/....

$ git pull upstream main

$ git push

Android Studio 現在已經學會了使用 GitHub fork 存儲庫(您甚至不必通過控制台命令添加“上游”遠程存儲庫)。

打開菜單VCSGit

並注意最后兩個彈出菜單項:

  • Rebase 我的 GitHub 分支

  • 創建拉取請求

試試看。 我使用第一個來同步我的本地存儲庫。 無論如何,在您單擊“Rebase my GitHub fork”后,將可以在 Android Studio 中訪問來自父遠程存儲庫(“上游”)的分支,並且您將能夠輕松地使用它們進行操作。

(我使用帶有“Git 集成”和“GitHub”插件的 Android Studio 3.0。)

在此處輸入圖像描述

這取決於您的存儲庫的大小以及您如何分叉它。

如果它是一個相當大的存儲庫,您可能希望以一種特殊的方式來管理它(例如刪除歷史記錄)。 基本上,您可以獲得當前版本和上游版本之間的差異,提交它們,然后將它們挑選回 master。

試試看 這個 它描述了如何處理大型 Git 存儲庫以及如何使用最新更改將它們上傳到上游。

我想補充一下@krlmlr 的答案

最初,分叉的存儲庫有一個名為master的分支。 如果您正在開發新功能或修復,您通常會創建一個新的分支feature並進行更改。

如果您希望分叉存儲庫與父存儲庫同步,您可以為Pull 應用程序在功能分支中)設置一個配置文件( pull.yml ),如下所示:

version: "1"
rules:
  - base: feature
    upstream: master
    mergeMethod: merge
  - base: master
    upstream: parent_repo:master
    mergeMethod: hardreset

這使分叉存儲庫的master分支與父存儲庫保持同步。 它通過合並相同的分叉存儲庫的master分支來保持分叉存儲庫的feature分支更新。 這假設feature分支是包含配置文件的默認分支。

這里有兩種合並hardreset mergemethods它有助於強制在分叉的 repo 的master分支中與父 repo 同步更改,另一種方法是merge 此方法用於合並您在feature分支中所做的更改以及由於master分支中的強制同步而完成的更改。 在合並沖突的情況下,拉取應用程序將允許您在拉取請求期間選擇下一個操作過程。

您可以在此處閱讀有關基本和高級配置以及各種mergemethods的信息。

我目前在我的分叉存儲庫中使用此配置,以確保此處請求增強功能保持更新。

試試這個,單擊“獲取上游”以從上游主同步您的分叉存儲庫。 在此處輸入圖像描述

保持分叉存儲庫始終保持更新有兩個主要方面。

1. 從 fork master 創建分支在那里進行更改

因此,當您的Pull Request被接受時,您可以安全地刪除分支,因為當您使用上游更新它時,您貢獻的代碼將存在於您的分叉存儲庫的主庫中。 這樣,您的 master 將始終處於干凈狀態,可以創建一個新分支來進行另一次更改。

2.為fork master創建一個計划的工作自動更新

這可以通過cron來完成。 如果您在 linux 中執行此操作,這是一個示例代碼。

$ crontab -e

將此代碼放在crontab file中,以每小時執行一次作業。

0 * * * * sh ~/cron.sh

然后創建cron.sh腳本文件和與ssh-agent和/或期望git 交互,如下所示

#!/bin/sh
WORKDIR=/path/to/your/dir   
REPOSITORY=<name of your repo>
MASTER="git@github.com:<username>/$REPOSITORY.git"   
UPSTREAM=git@github.com:<upstream>/<name of the repo>.git  

cd $WORKDIR && rm -rf $REPOSITORY
eval `ssh-agent` && expect ~/.ssh/agent && ssh-add -l
git clone $MASTER && cd $REPOSITORY && git checkout master
git remote add upstream $UPSTREAM && git fetch --prune upstream
if [ `git rev-list HEAD...upstream/master --count` -eq 0 ]
then
    echo "all the same, do nothing"
else
    echo "update exist, do rebase!"
    git reset --hard upstream/master
    git push origin master --force
fi
cd $WORKDIR && rm -rf $REPOSITORY
eval `ssh-agent -k`

檢查您的分叉存儲庫。 它會不時顯示此通知:

這個分支甚至與<upstream> :master

在此處輸入圖像描述

使用這些命令(在幸運的情況下)

git remote -v
git pull
git fetch upstream
git checkout master
git merge upstream/master --no-ff
git add .
git commit -m"Sync with upstream repository."
git push -v

如果您使用 GitHub Desktop,只需 6 步(實際上只有 5 步)即可輕松完成。

打開 Github Desktop 並選擇您的存儲庫后,

  1. 轉到歷史選項卡
  2. 點擊搜索欄。 它將向您顯示所有可用的分支(包括來自父存儲庫的上游分支)
  3. 選擇相應的上游分支(它將是上游/主同步主分支)
  4. (可選)它將向您顯示上游分支中的所有提交。 您可以單擊任何提交以查看更改。
  5. 根據您的活動分支,在master / branch-name中單擊 Merge。
  6. 等待 GitHub Desktop 施展魔法。

以下面的 GIF 為例:

從父存儲庫同步分叉存儲庫中的上游分支

如果你想讓你的 GitHub 分支與各自的上游保持同步,還有專門為 GitHub 提供的這個 probot 程序: https ://probot.github.io/apps/pull/ 可以完成這項工作。 您需要在您的帳戶中允許安裝,這將使您的分叉保持最新。

如何在本地機器上更新你的分叉倉庫?

首先,檢查您的遙控器/主機

git remote -v

你應該有起源和上游。 例如:

origin  https://github.com/your___name/kredis.git (fetch)
origin  https://github.com/your___name/kredis.git (push)
upstream    https://github.com/rails/kredis.git (fetch)
upstream    https://github.com/rails/kredis.git (push)

之后轉到主要:

git checkout main

並從上游合並到主要:

git merge upstream/main
rm -rf oldrepository
git clone ...

可能有更微妙的選擇,但這是我確信我的本地存儲庫與上游相同的唯一方法。

從 github 頁面刪除您的遠程開發人員

然后應用這些命令:

1) git branch -D dev
2) git fetch upstream
3) git checkout master
4) git fetch upstream && git fetch upstream --prune && git rebase upstream/master && git push -f origin master
5) git checkout -b dev
6) git push origin dev
7) git fetch upstream && git fetch upstream --prune && git rebase upstream/dev && 8) git push -f origin dev

要查看您的配置,請使用以下命令:

git remote -v

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM