簡體   English   中英

在git分支上工作

[英]working on git branch

我已經做了很多閱讀,但是對於在不同地方的git分支上如何工作仍不太清楚。 怎么做?

首先,我必須在分支機構工作的原因是我確實有一個“上游”存儲庫,我需要不時將其重新建立到我的master 因此,要保持上游的插件干凈,我需要在git分支上工作。

UPDATE2:

好。 它比我現在想的要復雜得多。 我從源位置執行的方法是, git checkout -b newfeature然后推送git push -u origin newfeature ,這是在“上游”存儲庫以及我自己的master庫的頂部完成的,按照

問題是我想像在普通git中一樣在這樣的git分支上工作-即,當我執行某種git push ,我期望從另一位置進行某種git pull以獲取最新版本。更新。

當我從第二名開始進行git pull ,我Already up-to-date 即,我要使用的遠程分支對我不可用。

PS。 我從http://longair.net/blog/2009/04/16/git-fetch-and-merge/找到的信息

如果要基於遠程跟蹤分支創建本地分支(即為了在其上實際工作),則可以使用git branch –track或git checkout –track -b來完成,這很相似,但是它也會切換您的新創建的本地分支的工作樹。 例如,如果您在git branch -r中看到想要的一個名為origin / reformed的遠程跟蹤分支,則可以使用以下命令:

git checkout --track -b refactored origin/refactored

但是,這就是我從源位置的git branch -r獲得的內容。

$ git branch -r
  origin/HEAD -> origin/master
  origin/master

即,沒有名為Origin / something的遠程跟蹤分支,但是我顯然在一個分支中工作:

$ git status . 
On branch newfeature
nothing to commit, working directory clean

$ git branch -vv
  master     55e1d6f [origin/master] Remove ...
* newfeature 8c4266a - [+] add ...

由於-r表示遠程跟蹤分支,因此我從第二名獲得git branch -r結果也相同。

更新3

最后,我可以確認問題出在我的源端,即,未列出遠程跟蹤分支。 再一次將它們並排列出。

首先,我目前的不良來源:

$ git branch -r
  origin/HEAD -> origin/master
  origin/master

$ git branch -vv
  master     55e1d6f [origin/master] Remove ...
* newfeature 8c4266a - [+] add ...

第二,應為:

$ git branch -r
  origin/HEAD -> origin/master
  origin/master
  origin/newfeature

$ git branch -vv
  master     7b1fc0f [origin/master] Add readme
* newfeature 7b1fc0f [origin/newfeature] Add readme
                     ^^^^^^^^^^^^^^^^^^^

git config --get-all remote.origin.fetch的輸出在兩個站點上都是相同的+refs/heads/master:refs/remotes/origin/master

$ git config --get-all remote.origin.fetch
+refs/heads/master:refs/remotes/origin/master

最終更新

感謝@torek的不懈幫助,我終於弄明白了。 這是按@torek指示修復.git/config文件之后的最后步驟:

git checkout master
# then fix the `.git/config` file
git config --edit

$ git branch -vv
* master     55e1d6f [origin/master] Remove ...
  newfeature 8c4266a [origin/newfeature: gone] - [+] add ...
                                         ^^^^

$ git branch -r
  origin/HEAD -> origin/master
  origin/master
  upstream/master
# The "origin/newfeature" is missing

$ git checkout newfeature
Switched to branch 'newfeature'
Your branch is based on 'origin/newfeature', but the upstream is gone.
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  (use "git branch --unset-upstream" to fixup)

$ git branch --set-upstream-to origin/newfeature
error: the requested upstream branch 'origin/newfeature' does not exist
hint: 
hint: If you are planning on basing your work on an upstream
hint: branch that already exists at the remote, you may need to
hint: run "git fetch" to retrieve it.
hint: 
hint: If you are planning to push out a new local branch that
hint: will track its remote counterpart, you may want to use
hint: "git push -u" to set the upstream config as you push.

$ git push -u origin newfeature
Branch newfeature set up to track remote branch newfeature from origin.
Everything up-to-date

$ git branch -r
  origin/HEAD -> origin/master
  origin/master
  origin/newfeature
  upstream/master
# The "origin/newfeature" is now listed

$ git branch -vv
  master     55e1d6f [origin/master] Remove ...
* newfeature 8c4266a [origin/newfeature] - [+] add ...

# Horay!!!

因此,首先要回顧一下,要使事情正確,請按照http://www.gitguys.com/topics/adding-and-removing-remote-branches中的說明進行操作。 通過那個小演示,我能夠獲得超過正確結果的結果。 也就是說,我一直遵循的方向

可能或可能不是原因。 但是,如果您遇到類似的情況,現在我們可以解決此問題。

最終更新結束

因此,讓我問最后一個問題-是否可以糾正我的不良來源?

根據
結帳跟蹤的遠程分支 ,我認為問題出在我的源頭,即,我沒有在跟蹤的遠程分支部分中列出我的分支。 這是我的:

$ git remote show origin
* remote origin
  Fetch URL: git@github.com:me/myproj.git
  Push  URL: git@github.com:me/myproj.git
  HEAD branch: master
  Remote branch:
    master tracked
  Local branches configured for 'git pull':
    master     merges with remote master
    newfeature merges with remote newfeature
  Local refs configured for 'git push':
    master     pushes to master     (up to date)
    newfeature pushes to newfeature (up to date)

當我從第二個位置執行git remote show origin ,我沒有看到那里列出的newfeature。

更新:

我從第二名看到git ls-remotenewfeature

$ git ls-remote
From git@github.com:me/myproj.git
55e1d6fd9048336c7f0b178fbbf78231ca28ff06        HEAD
55e1d6fd9048336c7f0b178fbbf78231ca28ff06        refs/heads/master
8c4266a6a98f498c129a2a9e806e00e6c6d196b1        refs/heads/newfeature
8c4266a6a98f498c129a2a9e806e00e6c6d196b1        refs/tags/v1

但是,我從第二位不知道如何使用它:

$ git checkout --track -b newfeature
Branch newfeature set up to track local branch master.
Switched to a new branch 'newfeature'

並且git log沒有顯示我已經發布到github的提交。

也許我不應該使用-b 好吧,我必須:

$ git checkout --track newfeature
fatal: Missing branch name; try -b

$ git checkout newfeature
error: pathspec 'newfeature' did not match any file(s) known to git.

根據以下評論,這是拼圖的最后一部分(我希望如此)。 我從以下請求輸出:

git config --get-all remote.origin.fetch

那是一行:

+refs/heads/master:refs/remotes/origin/master

此輸出不是正常設置(盡管允許)。 正常設置為:

+refs/heads/*:refs/remotes/origin/*

我認為最簡單的解決方法是運行:

git config --edit

這將在此存儲庫的Git配置文件(通常是.git/config )上打開您的編輯器。 在這里,您將看到以下三行:

[remote "origin"]
    url = [whatever the URL is]
    fetch = +refs/heads/master:refs/remotes/origin/master

第三行應為:

    fetch = +refs/heads/*:refs/remotes/origin/*

即,兩次出現的master都應替換為*

這些fetch =行控制git fetch的行為。 每行提供一個refspec ,僅比一對引用名稱多。 現有的(功能失常的)refspec表示您的Git應該從origin (在這種情況下為GitHub)中選擇分支master ,然后將其復制到遠程跟蹤分支的origin/master

正確的refspec表示您的Git應該從origin拾取每個分支( * ),並將每個分支復制到相應的遠程跟蹤分支( origin/* )。

(前面的加號告訴Git即使復制操作不是快進操作,也應該復制這些引用。對於遠程跟蹤分支,這就是您想要的。)

一旦這個是固定的, git fetch origin將拿起所有的GitHub的分支,並且所有剩下的工作就是確保newfeature ,在每個倉庫的,有origin/newfeature設置為其上游。 另外,在存儲庫newfeature已經master設置為它的上游,運行:

git checkout newfeature
git branch --set-upstream-to origin/newfeature

(在尚未具有newfeature分支的任何存儲庫中,請參見下文。)


新答案主要基於最新更新中的新問題(可能確實應該新問題)。 這又是(新)問題,因為否則我無法直截了當地。

更新:

我從第二名看到git ls-remotenewfeature

 $ git ls-remote From git@github.com:me/myproj.git 55e1d6fd9048336c7f0b178fbbf78231ca28ff06 HEAD 55e1d6fd9048336c7f0b178fbbf78231ca28ff06 refs/heads/master 8c4266a6a98f498c129a2a9e806e00e6c6d196b1 refs/heads/newfeature 8c4266a6a98f498c129a2a9e806e00e6c6d196b1 refs/tags/v1 

但是,我從第二位不知道如何使用它:

 $ git checkout --track -b newfeature Branch newfeature set up to track local branch master. Switched to a new branch 'newfeature' 

並且git log沒有顯示我已經發布到github的提交。

也許我不應該使用-b

確實,這就是(新)問題的根源。

由於輸出的第二行和第三行,我們可以看出:

Branch newfeature set up to track local branch master .
Switched to a new branch 'newfeature'

我在這里添加了三種不同的強調方式( 斜體粗體粗體斜體 ),以便我可以討論三種不同的觀點。

首先,Git告訴我們這是一個分支。 很好:這就是我們想要的! 我們想在這個存儲庫中創建一個新的(和本地的 )分支名稱。

但是我們不希望新的本地分支跟蹤另一個本地分支。 告訴我們,它正在跟蹤(本地)分支主管 我們希望它跟蹤一個遠程跟蹤分支,可能是origin/newfeature

命令git checkout -b newbranch告訴Git創建一個新的本地分支newbranch ,沒有上游設置。 添加--track會修改命令,以告訴Git創建帶有上游集的newbranch ,但是Git設置的上游就是當前分支。

使用git checkout --track newbranch ,不帶-b ,會做很多不同的事情。 使用git checkout newbranch既不 --track 也不 -b ,做第三是兩回事。 我們到達這里的方式是這些長期無聊的歷史錯誤中的另一件事,但實際上,通常是我們想要的第三種不同的東西。

通常我們只使用git checkout somebranch來切換到某些現有分支somebranch 這通常很簡單:我們可能現在就在master ,而在我們開始工作之前就應該進行develop ,因此我們git checkout develop並從master切換到develop (但后來Git的嘗試是有益的,並讓我們先開始改變代碼, 然后切換到develop這主要是實際工作,而且有益的,但它會導致初學者困惑:為什么現在的Git讓我現在切換,但如果我進行了其他更改,它不會讓我切換?請參閱Git-當當前分支上有未提交的更改時,簽出另一個分支以了解詳細信息。)

在另一種嘗試是有益的,GIT中增加了“做什么,我的意思是”(DWIM)選項git checkout ,這樣,如果你寫git checkout newfeature沒有 newfeature的是,它會創建 newfeature對你來說, 上游集,基於origin/newfeature (這被過度簡化;請參見下文。)因此:

$ git checkout newfeature

調用DWIM代碼(“做什么,我的意思是說,不是我居然說”):Git的猜測你的意思是使用下面的命令:

git checkout -b newfeature --track origin/newfeature

這是完全拼寫出請求:“創建newfeature的基礎上,其提交到origin/newfeature點,現在,與origin/newfeature設定為上游為newfeature

也就是說,它通常會為您完成所有這一切。 DWIM代碼很聰明,但並不完美。 為此,必須滿足以下所有條件:

  • 您的存儲庫至少有一個遠程服務器。 它可以有多個遙控器,例如,您可以將githublaptop作為兩個遙控器(在本示例中, 兩者均未命名為originorigin只是標准的遙控器名稱)。
  • 您的存儲庫至少有一個遠程跟蹤分支,該分支正在跟蹤該遠程上名為newfeature的分支。 在此示例中,如果存在遠程跟蹤分支github/newfeature ,則可以滿足此要求。
  • 最后,當您有多個遠程站點時,事情就變得混亂了。您的存儲庫必須只有一個這樣的遠程跟蹤分支。 在這種情況下,如果github/newfeature laptop/newfeature存在,則DWIM代碼將失敗!

確保只有一個遠程跟蹤分支存在

目前尚不清楚當前存儲庫中的origin/newfeature是否實際上作為遠程跟蹤分支存在。

請記住,每個Git存儲庫都非常獨立於其他所有Git存儲庫。 這意味着GitHub上的存儲庫G是否具有newfeature不會告訴我們Laptop上的存儲庫L是否具有newefature和/或origin/newfeature 而且,知道其中任何一個並不能告訴我們在Work-machine上的存儲庫W是否具有其中任何一個。

如果我們現在在Work-machine上,在存儲庫W中 ,並且已經設置了兩個遙控器githublaptop ,我們可以運行git fetch github與GitHub聯系,並從存儲庫G中 git fetch github newfeature (它顯示在git ls-remote輸出)並創建或更新遠程跟蹤分支github/newfeature

我們還可以運行git fetch laptop來聯系筆記本電腦(假設筆記本電腦已打開並且已連接到網絡並且可以訪問)。 如果便攜式計算機上的存儲庫L中newfeature ,我們將獲取laptop/newfeature

如果這樣做,我們將在git checkout破壞DWIM代碼,因為現在我們有兩個可能的git checkout newfeature上游。

有多個遙控器和兩個或多個可能的上游沒有錯

具有倉庫W和遠程githublaptop此設置很好。 它只是破壞了DWIM代碼。 您可以寫出您的真實意思,讓Git做到您所說的,而不是依靠Git來猜測您的意思

git checkout -b lapfeature --track laptop/newfeature
git checkout -b hubfeature --track github/newfeature

現在,在您的工作機W資源庫中,本地分支lapfeature跟蹤laptop/newfeature ,這是您在筆記本電腦上提交的代碼,而本地分支hubfeature跟蹤github/newfeature ,這是您要推送到github的版本。 (這些也不必保持同步...盡管如果讓它們分開太遠,則可能會使自己不快樂。:-))

雖然DWIM代碼很方便

能夠git checkout newfeature 很好 為此,您必須小心擁有多少個遙控器。 僅具有一個遠程平常origin -makes更方便這些功能的工作的。 當只有一個真相來源時,例如“最新版本始終是GitHub上的所有內容”,這也將更加清楚。

缺點是您隨后必須通過GitHub來回推送所有內容。 (通常可以正常工作,但是還記得GitHub宕機的那一天嗎?

Git令人困惑,因為...

維護Git的人們似乎喜歡將盡可能多的功能推入git checkout等命令中,即使這樣會導致類似這樣的奇怪結果。 請注意, git checkout可以:

  • 切換到現有分支
  • 切換到特定的提交(“分離頭”模式)
  • 創建一個新分支
  • 創建一個新的“孤立”分支(尚未創建的分支)
  • 創建分支的引用日志
  • 從提交中提取文件
  • 從索引/暫存區中提取文件
  • 恢復合並沖突(從git add撤消合並解析)
  • 交互式地修補工作樹中的文件

這些都相關,但是它們也與移動分支( git reset )甚至進行差異( git checkout --patch必須進行差異)之類的動作有關。 那么,為什么它們都在一個git checkout命令中呢? 特別是當這導致諸如“有時允許分支切換,有時不允許分支切換,並且git checkout otherbranch無損但git checkout otherbranch path/to/file具有高度破壞性”之類的復雜情況時。


以下答案是針對原始問題的,而不是針對更新的問題。

根據您的評論答復 ,您正在尋找可與遠程分支跟蹤分支以及遠程分支一起使用的方法 好像這些應該是相似的東西,如果不是相同的,不是嗎? 但是它們都完全不同,我認為許多介紹也對它們進行了相當差的解釋。 毫無疑問,其中一些是由於歷史原因造成的(Git的遠程控制和遠程跟蹤分支是2008-2012年的新發明;它們在2013年中后期成功成立)。 如果您的Git版本至少為1.8.4,最好是2.0或更高版本,則可以忽略一些歷史問題。 (如果沒有,請顯示您的Git版本-運行git --version ,將有變通辦法或要設置的配置旋鈕等。)

首先,一些定義:

  • 遙控器只是一個名稱,例如origin ,Git可以在其​​中存儲一些項目。 最重要的一個是URL,它指定要推送到和從中提取的位置。
  • 分支是模棱兩可的(請參閱“分支”到底是什么意思? )。

    分支名稱是類似於masternewfeature的名稱; 它包含一個(單個)Git提交的ID。 常規(本地)分支名稱是更通用的Git 引用的一種特定形式。 引用有前綴:本地分支都以refs/heads/前綴,因此master實際上是refs/heads/master ,依此類推。

    有關“分支”的其他含義,請參見鏈接的問題。 請注意,分支名稱會自動更新:在該分支上進行新提交時,會導致該分支名稱指向新提交。 這是分支增長的機制。

  • 遠程跟蹤分支是至少在內部以refs/remotes/開頭的引用。 這些引用還使用遠程服務器的名稱進行了限定,因此,所有origin的遠程跟蹤分支都以refs/remotes/origin/開頭。 與常規分支名稱一樣,Git通常會刪除前綴,僅向您顯示origin/masterorigin/newfeature

接下來,使用Git或任何分布式版本控制系統; 例如,對於Mercurial來說,情況也是如此-您必須偶爾記住,有多個獨立的1存儲庫,它們並不總是同步的。 在Git中,兩個存儲庫之間的同步發生在git fetchgit push 這兩個命令是要點2 ,您(和您的Git)實際上可以同時看到兩個不同的存儲庫。 我認為運行git ls-remote origin是有教育意義的,它從遠程讀取但沒有進行本地更改:您應該立即嘗試一下,看看它顯示了什么。

遠程跟蹤分支的主要目的是:在您自己的Git存儲庫中,跟蹤Git上一次與其同步的分支(常規的本地分支名稱)指向的位置。 當您運行git fetch origin ,您的Git與他們的Git聯系,下載所有必需的內容,然后更新所有名為origin/*遠程跟蹤分支,以匹配它剛在origin看到的分支。

一個git push origin yourcommit:theirname告訴你的Git調用了自己的Git,發送給他們任何承諾和所需的其他對象,然后問他們(禮貌),請設置其分支機構theirname指向特定提交您確定yourcommit 也就是說,您可以git push origin HEAD:name或-假設您的HEAD提交是a1234567 - git push origin a1234567:name ,您的Git會發送commit a1234567以及其他必要的內容,以便他們將name設置為指向a1234567 (您的Git和他們的Git在推送開始時就需要哪些對象進行了對話。請注意,您的Git,他們的Git以及實際上世界上的每個Git都始終同意每次提交的ID!是編寫分布式VCS的棘手部分之一。)

通常,您將使用自己的分支名稱之一 ,在這種情況下,您可以省略:theirname部分,您的Git會要求其Git為分支設置相同的名稱。 也就是說,您可以git push origin newfeature ,並且Git將向他們發送分支newfeature的尖端提交,以及完成分支所需的所有其他提交和文件,然后禮貌地要求他們設置newbranch

通常,如果此設置是作為快進操作的更新, 或者如果它創建了名稱, 或者為此刪除了名稱,則遵循禮貌的請求。 但是,接收方Git有機會以任何理由拒絕。 (有關詳細信息,請參見其他SO發布。)如果推送在遠程上創建了一個分支,這還將在您的存儲庫中創建一個新的遠程跟蹤分支,因為遠程上現在有一個新的(本地,到遠程)分支。 ,您的Git應該跟蹤。 如果該分支已經存在於遠程服務器上,並且接受了更新,則您的Git應該更新您的遠程跟蹤分支。

推送操作可以 (但默認情況下)不設置本地分支的上游 有關更多信息,請參見鏈接的答案。

一旦分支存在於遠程服務器上,您就可以使用git push從更新的地方(筆記本電腦或工作之類的東西)將新的提交推送到遠程服務器,然后先進行git fetch ,再進行git mergegit rebase遠程復制提交遠程。 如果您已經設置了上游設備,或者以其他方式正確配置了所有歷史行李配置旋鈕,則無需為此使用大量參數。 (盡管您將需要使用--force-with-lease--force / -f--force+加號前綴語法來強制推送不是快進操作的更新。)

還要注意,您可以有多個遙控器。 如果將便攜式計算機設置為工作計算機的遠程計算機,反之亦然,則只要它們在網絡上彼此連接(只要您具有ssh或類似的訪問權限,就可以在這些計算機之間)直接在這些計算機之間傳輸提交(這是從Linux機器上進行的操作)通常很容易)。 換句話說,你不必去通過GitHub上或一些其他集中的位置(雖然你仍然可以做,只要很方便)。


1在Git的情況下,它們非常獨立。 在Mercurial中,由於分支名稱是全局的,因此與Git的標簽是全局的一樣,存儲庫被迫靠近在一起。

2可以同時“同時看到兩者”的其他方法是git ls-remotegit remote show ,但是這兩種方法都是嚴格只讀的。 fetch步驟將寫入您的存儲庫,而push步驟將寫入其存儲庫。

嘗試這個

git push --set-upstream origin BRANCHNAME

暫無
暫無

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

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