git

2016.12.4

雖然14年開發第一個項目時就已經接觸了git,當時xcode已經開始支持git,在github上面建立的倉庫,然后使用xcode去合并代碼,不過后來都在獨立開發項目,對git的使用算不上熟練,上周五加入了響巢看看大家庭,以后工作中會經常使用git,所以今天就來熟練一下git。主要途徑是搜索引擎搜索到的一個不錯的入門教程

安裝Git

xcode自帶git,也可以通過homebrew,或者去github上面搜索一個安裝腳本運行一下,或者直接下載git安裝

創建版本庫

版本庫又名倉庫,英文名repository,我們比著上面推薦給大家的入門教程來做一遍,首先創建路徑,然后初始化版本庫,這時候我們會在目標路徑下生成一個".git"文件

注意:Git 能跟蹤文本文件的改動,而音視頻,圖片等二進制文件的改變Git只能跟蹤文件大小的變動,無法跟蹤具體的變化細節,Word格式是二進制格式,版本控制系統是沒法跟蹤Word文件的改動的,所以我們要以純文本方式編寫文件

添加文件到版本庫

現在我們添加一個txt文件進入我們的git倉庫,主要用到兩個操作,add與commit。ok,我們來具體操作一下。

說明:-m 這個參數是本次提交的詳細說明,可以不加,但是最好帶著。

修改提交

這個階段主要用到的操作有status,是查看git當前的狀態,diff,告知git詳細的改變,提交與之前一樣,add與commit,來,我們比著教程做一下。

版本回退

前面已經修改提交,但是如果你后悔了,怎么回退之前的版本呢,如果回退后又反悔了呢,哈哈,好糾結。這個部分主要用的的操作有log,log用來打印我們各個版本的一個列表,可以通過傳遞--pretty=oneline參數使顯示格式更加簡約,在每次commit之前都有一串字符串,這個我們叫做commitid,在git里面有一個被稱作HEAD的指針,HEAD指針指向的commit就是我們當前操作的commit,我們可以通過操作HEAD的指向來對我們當前版本進行切換,從而實現回退,主要的操作是reset --hard HEAD^ 或者是 <commitid>,commitid不需要全部寫完,這里只是用來篩選,寫五個左右就足夠了,HEAD^代表HEAD指向的前一個,HEAD^^代表指向的前第二個,HEAD~100,代表指向的前第100個。還有一個叫做reflog的操作,打印的是HEAD位置發生改變的操作的列表。下面我們比著教程來做一下。

工作區與暫存區

工作區(Working Directory)就是你在電腦里能看到的目錄,這里msgit文件夾就是一個工作區。

版本庫(Repository)工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。

圖片來源

修改撤銷

主要用到的命令是 git checkout -- file,這個命令就是讓這個文件回到最近一次git commit或git add時的狀態,git checkout -- file命令中的--很重要,沒有--,就變成了“切換到另一個分支”的命令。命令git reset HEAD file可以把暫存區的修改撤銷掉(unstage),重新放回工作區,當我們用HEAD時,表示最新的版本。

刪除文件

刪除文件主要用到的命令是git rm,之后要記得git commit。如果說我們在工作區錯誤的刪除了某一個文件,我們可以通過git checkout -- <filename> 來把誤刪的文件恢復到最新版本。下面我們來實際操作一下。

遠程倉庫

接下來我們要在GitHub上實現我們的遠程倉庫

下面這一段是引用

第1步:創建SSH Key。在用戶主目錄下,看看有沒有.ssh目錄,如果有,再看看這個目錄下有沒有id_rsa和id_rsa.pub這兩個文件,如果已經有了,可直接跳到下一步。如果沒有,打開Shell(Windows下打開Git Bash),創建SSH Key:

$ ssh-keygen -t rsa -C "youremail@example.com"

你需要把郵件地址換成你自己的郵件地址,然后一路回車,使用默認值即可,由于這個Key也不是用于軍事目的,所以也無需設置密碼。

如果一切順利的話,可以在用戶主目錄里找到.ssh目錄,里面有id_rsa和id_rsa.pub兩個文件,這兩個就是SSH Key的秘鑰對,id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。

第2步:登陸GitHub,打開“Account settings”,“SSH Keys”頁面:

然后,點“Add SSH Key”,填上任意Title,在Key文本框里粘貼id_rsa.pub文件的內容:

點“Add Key”,你就應該看到已經添加的Key:

為什么GitHub需要SSH Key呢?因為GitHub需要識別出你推送的提交確實是你推送的,而不是別人冒充的,而Git支持SSH協議,所以,GitHub只要知道了你的公鑰,就可以確認只有你自己才能推送。

當然,GitHub允許你添加多個Key。假定你有若干電腦,你一會兒在公司提交,一會兒在家里提交,只要把每臺電腦的Key都添加到GitHub,就可以在每臺電腦上往GitHub推送了。

最后友情提示,在GitHub上免費托管的Git倉庫,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放進去。

如果你不想讓別人看到Git庫,有兩個辦法,一個是交點保護費,讓GitHub把公開的倉庫變成私有的,這樣別人就看不見了(不可讀更不可寫)。另一個辦法是自己動手,搭一個Git服務器,因為是你自己的Git服務器,所以別人也是看不見的。這個方法我們后面會講到的,相當簡單,公司內部開發必備。

小明去查看了本地目錄并沒有.ssh目錄,然后在終端輸入$ ssh-keygen -t rsa -C "我的郵箱"確實就出現了.ssh目錄,依據上面的步驟,在GitHub上面添加好了sshkey,需要說明的是.ssh是隱藏目錄,我們需要在終端輸入defaults write com.apple.finder AppleShowAllFiles YES就可以查看隱藏文件了

添加遠程庫(引用

現在的情景是,你已經在本地創建了一個Git倉庫后,又想在GitHub創建一個Git倉庫,并且讓這兩個倉庫進行遠程同步,這樣,GitHub上的倉庫既可以作為備份,又可以讓其他人通過該倉庫來協作,真是一舉多得。

首先,登陸GitHub,然后,在右上角找到“Create a new repo”按鈕,創建一個新的倉庫:

在Repository name填入learngit,其他保持默認設置,點擊“Create repository”按鈕,就成功地創建了一個新的Git倉庫:

目前,在GitHub上的這個learngit倉庫還是空的,GitHub告訴我們,可以從這個倉庫克隆出新的倉庫,也可以把一個已有的本地倉庫與之關聯,然后,把本地倉庫的內容推送到GitHub倉庫。

現在,我們根據GitHub的提示,在本地的learngit倉庫下運行命令:

$ git remote add origin git@github.com:michaelliao/learngit.git

請千萬注意,把上面的michaelliao替換成你自己的GitHub賬戶名,否則,你在本地關聯的就是我的遠程庫,關聯沒有問題,但是你以后推送是推不上去的,因為你的SSH Key公鑰不在我的賬戶列表中。

添加后,遠程庫的名字就是origin,這是Git默認的叫法,也可以改成別的,但是origin這個名字一看就知道是遠程庫。

下一步,就可以把本地庫的所有內容推送到遠程庫上:

$ git push -u origin master

Counting objects: 19, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (19/19), done.

Writing objects: 100% (19/19), 13.73 KiB, done.

Total 23 (delta 6), reused 0 (delta 0)

To git@github.com:michaelliao/learngit.git

* [new branch]? ? ? master -> master

Branch master set up to track remote branch master from origin.

把本地庫的內容推送到遠程,用git push命令,實際上是把當前分支master推送到遠程。

由于遠程庫是空的,我們第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令。

推送成功后,可以立刻在GitHub頁面中看到遠程庫的內容已經和本地一模一樣:

從現在起,只要本地作了提交,就可以通過命令:

$ git push origin master

把本地master分支的最新修改推送至GitHub,現在,你就擁有了真正的分布式版本庫!

SSH警告

當你第一次使用Git的clone或者push命令連接GitHub時,會得到一個警告:

The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.

RSA key fingerprint is xx.xx.xx.xx.xx.

Are you sure you want to continue connecting (yes/no)?

這是因為Git使用SSH連接,而SSH連接在第一次驗證GitHub服務器的Key時,需要你確認GitHub的Key的指紋信息是否真的來自GitHub的服務器,輸入yes回車即可。

Git會輸出一個警告,告訴你已經把GitHub的Key添加到本機的一個信任列表里了:

Warning: Permanently added 'github.com' (RSA) to the list of known hosts.

這個警告只會出現一次,后面的操作就不會有任何警告了。

如果你實在擔心有人冒充GitHub服務器,輸入yes前可以對照GitHub的RSA Key的指紋信息是否與SSH連接給出的一致。

接下來我們自己做一遍

從遠程庫克隆

這個應該是多人協作時一定會用到的

我們新建一個名字叫做hahaha的遠程倉庫。接下來我們使用git clone。

一個git倉庫,有https地址和ssh地址兩種,根據自己的需要去選擇就可以,一般情況下,兩者都可以,在這里查看

下面是我運行的結果

分支

分支常用的命令。查看分支:git branch 創建分支:git branch <name>?切換分支:git checkout <name> 創建+切換分支:git checkout -b <name> 合并某分支到當前分支:git merge <name> 刪除分支:git branch -d <name>

分支策略(引用)

在實際開發中,我們應該按照幾個基本原則進行分支管理:

首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發布時,再把dev分支合并到master上,在master分支發布1.0版本;

你和你的小伙伴們每個人都在dev分支上干活,每個人都有自己的分支,時不時地往dev分支上合并就可以了。

所以,團隊合作的分支看起來就像這樣:

Bug分支

通常我們在工作中接到了修復某個bug的任務,這時候我們就需要來創建一個bug分支來修復我們的bug,但是如果當前我們手中的工作尚未完成怎么辦呢,git提供了一個操作可以保存當前的工作現場 stash,等以后方便恢復現場繼續工作

我們可以通過git stash list命令查看當前保存的工作現場。

使用git stash apply恢復,但是恢復后,stash內容并不刪除,你需要用git stash drop來刪除,另一種方式是用git stash pop,恢復的同時把stash內容也刪了

多人協作(引用

當你從遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin。

要查看遠程庫的信息,用git remote:

$ git remote

origin

或者,用git remote -v顯示更詳細的信息:

$ git remote -v

origin? git@github.com:michaelliao/learngit.git (fetch)

origin? git@github.com:michaelliao/learngit.git (push)

上面顯示了可以抓取和推送的origin的地址。如果沒有推送權限,就看不到push的地址。

推送分支(引用)

推送分支,就是把該分支上的所有本地提交推送到遠程庫。推送時,要指定本地分支,這樣,Git就會把該分支推送到遠程庫對應的遠程分支上:

$ git push origin master

如果要推送其他分支,比如dev,就改成:

$ git push origin dev

但是,并不是一定要把本地分支往遠程推送,那么,哪些分支需要推送,哪些不需要呢?

master分支是主分支,因此要時刻與遠程同步;

dev分支是開發分支,團隊所有成員都需要在上面工作,所以也需要與遠程同步;

bug分支只用于在本地修復bug,就沒必要推到遠程了,除非老板要看看你每周到底修復了幾個bug;

feature分支是否推到遠程,取決于你是否和你的小伙伴合作在上面開發。

抓取分支(引用)

多人協作時,大家都會往master和dev分支上推送各自的修改。

現在,模擬一個你的小伙伴,可以在另一臺電腦(注意要把SSH Key添加到GitHub)或者同一臺電腦的另一個目錄下克?。?/p>

$ git clone git@github.com:michaelliao/learngit.git

Cloning into 'learngit'...

remote: Counting objects: 46, done.

remote: Compressing objects: 100% (26/26), done.

remote: Total 46 (delta 16), reused 45 (delta 15)

Receiving objects: 100% (46/46), 15.69 KiB | 6 KiB/s, done.

Resolving deltas: 100% (16/16), done.

當你的小伙伴從遠程庫clone時,默認情況下,你的小伙伴只能看到本地的master分支。不信可以用git branch命令看看:

$ git branch

* master

現在,你的小伙伴要在dev分支上開發,就必須創建遠程origin的dev分支到本地,于是他用這個命令創建本地dev分支:

$ git checkout -b dev origin/dev

現在,他就可以在dev上繼續修改,然后,時不時地把dev分支push到遠程:

$ git commit -m "add /usr/bin/env"

[dev 291bea8] add /usr/bin/env

1 file changed, 1 insertion(+)

$ git push origin dev

Counting objects: 5, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (2/2), done.

Writing objects: 100% (3/3), 349 bytes, done.

Total 3 (delta 0), reused 0 (delta 0)

To git@github.com:michaelliao/learngit.git

fc38031..291bea8? dev -> dev

你的小伙伴已經向origin/dev分支推送了他的提交,而碰巧你也對同樣的文件作了修改,并試圖推送:$ git add hello.py $ git commit -m "add coding: utf-8"[dev bd6ae48] add coding: utf-8 1 file changed, 1 insertion(+)$ git push origin devTo git@github.com:michaelliao/learngit.git ! [rejected]? ? ? ? dev -> dev (non-fast-forward)error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'hint: Updates were rejected because the tip of your current branch is behindhint: its remote counterpart. Merge the remote changes (e.g. 'git pull')hint: before pushing again.hint: See the 'Note about fast-forwards' in 'git push --help' for details.推送失敗,因為你的小伙伴的最新提交和你試圖推送的提交有沖突,解決辦法也很簡單,Git已經提示我們,先用git pull把最新的提交從origin/dev抓下來,然后,在本地合并,解決沖突,再推送:$ git pullremote: Counting objects: 5, done.remote: Compressing objects: 100% (2/2), done.remote: Total 3 (delta 0), reused 3 (delta 0)Unpacking objects: 100% (3/3), done.From github.com:michaelliao/learngit? fc38031..291bea8? dev? ? ? ? -> origin/devThere is no tracking information for the current branch.Please specify which branch you want to merge with.See git-pull(1) for details? ? git pullIf you wish to set tracking information for this branch you can do so with:? ? git branch --set-upstream dev origin/git pull也失敗了,原因是沒有指定本地dev分支與遠程origin/dev分支的鏈接,根據提示,設置dev和origin/dev的鏈接:

$ git branch --set-upstream dev origin/dev

Branch dev set up to track remote branch dev from origin.

再pull:

$ git pull

Auto-merging hello.py

CONFLICT (content): Merge conflict in hello.py

Automatic merge failed; fix conflicts and then commit the result.

這回git pull成功,但是合并有沖突,需要手動解決,解決的方法和分支管理中的解決沖突完全一樣。解決后,提交,再push:

$ git commit -m "merge & fix hello.py"

[dev adca45d] merge & fix hello.py

$ git push origin dev

Counting objects: 10, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (5/5), done.

Writing objects: 100% (6/6), 747 bytes, done.

Total 6 (delta 0), reused 0 (delta 0)

To git@github.com:michaelliao/learngit.git

291bea8..adca45d? dev -> dev

因此,多人協作的工作模式通常是這樣:

首先,可以試圖用git push origin branch-name推送自己的修改;

如果推送失敗,則因為遠程分支比你的本地更新,需要先用git pull試圖合并;

如果合并有沖突,則解決沖突,并在本地提交;

沒有沖突或者解決掉沖突后,再用git push origin branch-name推送就能成功!

如果git pull提示“no tracking information”,則說明本地分支和遠程分支的鏈接關系沒有創建,用命令git branch --set-upstream branch-name origin/branch-name。

這就是多人協作的工作模式,一旦熟悉了,就非常簡單。

小結

查看遠程庫信息,使用git remote -v;

本地新建的分支如果不推送到遠程,對其他人就是不可見的;

從本地推送分支,使用git push origin branch-name,如果推送失敗,先用git pull抓取遠程的新提交;

在本地創建和遠程分支對應的分支,使用git checkout -b branch-name origin/branch-name,本地和遠程分支的名稱最好一致;

建立本地分支和遠程分支的關聯,使用git branch --set-upstream branch-name origin/branch-name;

從遠程抓取分支,使用git pull,如果有沖突,要先處理沖突。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1. 安裝 Github 查看是否安裝git: $ git config --global user.name "...
    Albert_Sun閱讀 13,736評論 9 163
  • 1.git的安裝 1.1 在Windows上安裝Git msysgit是Windows版的Git,從https:/...
    落魂灬閱讀 12,716評論 4 54
  • 2017年2月25日 晴 很少走沒有燈的路 因為膽量不那么夠 怪物最喜歡我悄無聲息忍受 野狗瞪著雙眼等候 我不出意...
    鮮栗子閱讀 93評論 0 0
  • 吾兒帥氣登舞臺 主持金融演講賽 當代青年多才俊 聲情并茂展風彩 中華文明數千載 詩詞歌賦抒情懷 閱讀朗誦風興起 傳...
    精忠報國_fdf3閱讀 340評論 3 0
  • 先上代碼 來源 相關的注釋已經直接放入代碼,當然不否認源代碼還有不少缺少考慮的東西,但是不能否認這個深度復制和判...
    yongningfu閱讀 483評論 0 0