本文將從 Git 的核心概念講起,詳細介紹常用命令、各階段版本回退、分支控制以及企業內常見的 Git 工作流。
Git 與 GitHub 簡介
Git 簡介
Git 是一個開源的分布式版本控制系統,由 Linus Torvalds 于 2005 年開發。它與集中式版本控制系統(如 SVN)不同,不需要依賴中央服務器,每個開發者的電腦上都有一個完整的版本庫,使得開發者可以在本地獨立進行代碼的提交、分支創建等操作,大大提高了開發的靈活性和效率。即使在沒有網絡的情況下,開發者也能正常開展工作,只需在有網絡時與遠程倉庫進行同步即可。
GitHub 簡介
GitHub 是一個基于 Git 的代碼托管平臺,它為開發者提供了遠程倉庫托管服務,同時還集成了代碼評審、issue 跟蹤、項目管理等功能,是全球最大的開源社區之一。開發者可以在 GitHub 上創建公共或私有倉庫,與其他開發者共享代碼、協作開發項目。除了托管代碼,GitHub 還為開源項目提供了展示和推廣的平臺,許多知名的開源項目(如muduo,sylar)都托管在 GitHub 上。
環境搭建:Windows 與 Ubuntu 下的 Git 安裝及 SSH 配置
Windows Git 環境搭建(含 SSH 私鑰公鑰配置)
- 下載安裝 Git:訪問 Git 官方網站(Git),下載適合 Windows 系統的 Git 安裝包。運行安裝包,按照默認選項一路點擊 “Next” 即可完成安裝。安裝完成后,在開始菜單中找到 “Git Bash”,打開它即表示 Git 安裝成功。
- 配置 SSH 密鑰:
ssh-keygen -t rsa -C "your_email@example.com"
#example: ssh-keygen -t rsa -C "12345678@qq.com"
-
- 打開 Git Bash,輸入以下命令生成 SSH 密鑰對,其中 “your_email@example.com” 替換為你的郵箱地址:
-
- 一路按回車鍵,會提示設置密鑰的保存路徑,默認路徑為 “C:/用戶/Administrator/.ssh”,可直接按回車鍵使用默認路徑。
-
- 接著會提示設置密碼,可直接按回車鍵不設置密碼,也可根據需要設置密碼。
-
- 密鑰生成成功后,在 “C:/用戶/Administrator/.ssh” 目錄下會生成 “id_rsa”(私鑰)和 “id_rsa.pub”(公鑰)兩個文件。
-
- 打開 “id_rsa.pub” 文件,復制其中的內容。
-
- 登錄 GitHub 或其他 Git 托管平臺,進入個人設置頁面,找到 “SSH and GPG keys” 選項,點擊 “New SSH key”,將復制的公鑰內容粘貼到 “Key” 輸入框中,設置一個標題,然后點擊 “Add SSH key” 完成配置。
Ubuntu Git 環境搭建(含 SSH 私鑰公鑰配置)
- 安裝 Git:打開終端,輸入以下命令安裝 Git:
sudo apt update
sudo apt install git
安裝完成后,輸入 “git --version” 命令,若顯示 Git 的版本信息,則表示安裝成功。
- 配置 SSH 密鑰:
ssh-keygen -t rsa -C "your_email@example.com"
-
- 在終端中輸入以下命令生成 SSH 密鑰對:
-
- 后續步驟與 Windows 系統下相同,設置密鑰保存路徑和密碼(可默認)。
-
- 生成的密鑰文件位于 “~/.ssh” 目錄下,同樣復制 “id_rsa.pub” 文件中的內容,添加到 Git 托管平臺的 SSH 密鑰設置中。
測試連接:
ssh -T git@github.com
核心概念:工作區、暫存區、本地倉庫與遠程倉庫
要熟練使用 Git,首先需要理解它的四個核心概念:工作區、暫存區、本地倉庫和遠程倉庫,以及它們之間的交互關系。
工作區
工作區就是你在電腦上實際操作的項目目錄,你對文件的新增、修改、刪除等操作都是在工作區進行的。例如,你在項目文件夾中新建了一個index.html文件,或者修改了style.css文件的內容,這些操作都發生在工作區。
暫存區
暫存區也叫索引區,它是一個臨時存放文件變更的區域。當你在工作區完成對文件的修改后,需要通過特定的命令(git add <filename>)將這些變更提交到暫存區。暫存區的作用是讓你可以選擇性地將工作區中的部分變更提交到本地倉庫,而不是一次性提交所有變更(想要提交所有變更可以使用:git add .)。你可以把暫存區想象成一個緩沖區,它保存了你下一次要提交到本地倉庫的內容。
本地倉庫
本地倉庫是存儲在你自己電腦上的代碼倉庫,它包含了項目的所有歷史版本和元數據。當你將暫存區的變更提交(git commit -m "提交說明")到本地倉庫后,這些變更就被永久地記錄下來了,你可以隨時查看歷史提交記錄、回滾到之前的版本等。本地倉庫是 Git 版本控制的核心,所有的版本管理操作都是基于本地倉庫進行的。
遠程倉庫
遠程倉庫是托管在網絡服務器上的代碼倉庫,它通常用于團隊協作。團隊成員可以將自己本地倉庫的變更推送到遠程倉庫(git push),也可以從遠程倉庫拉取其他成員的變更(git pull),從而實現代碼的共享和同步。常見的遠程倉庫托管平臺有 GitHub、GitLab、Gitee、GitCode 等。
四者之間的交互
工作區、暫存區、本地倉庫和遠程倉庫之間的交互是 Git 工作流程的核心。具體來說,交互過程如下:
- 在工作區對文件進行修改(新增、編輯、刪除等)。
- 使用git add命令將工作區中需要提交的變更添加到暫存區,此時暫存區記錄了這些變更。
- 使用git commit命令將暫存區的變更提交到本地倉庫,本地倉庫會生成一個新的版本記錄。
- 使用git push命令將本地倉庫的變更推送到遠程倉庫,讓其他團隊成員可以獲取這些變更。
- 當需要獲取遠程倉庫中其他成員的變更時,使用git pull或git fetch命令將遠程倉庫的變更拉取到本地倉庫,然后合并到工作區。
常用 Git 命令及操作流程
掌握常用的 Git 命令是使用 Git 的基礎,下面介紹一些最常用的命令及其用法,以及完整的操作流程。
初始化與配置
- git init:在當前目錄初始化一個新的 Git 倉庫,會創建一個隱藏的.git目錄,用于存儲倉庫的元數據。
- git config --global user.name "Your Name":配置全局的用戶名,提交代碼時會顯示該用戶名。
- git config --global user.email "your.email@example.com":配置全局的郵箱地址,提交代碼時會關聯該郵箱。
倉庫克隆與基礎查看命令
- git clone <remote_url>:從遠程倉庫克隆一個倉庫到本地,會在本地創建一個與遠程倉庫同名的目錄,并將倉庫內容下載到該目錄。克隆完成后,本地會生成一個默認的main分支,對應遠程的main分支。
- git status:查看工作區和暫存區的狀態,顯示哪些文件被修改、哪些文件未被跟蹤等信息。
- git branch:查看本地所有的分支,當前所在的分支會以*標記。
- git branch -r:查看遠程倉庫的所有分支。
工作區與暫存區操作
- git add <file>:將工作區中指定文件的變更提交到暫存區。例如,git add index.html將index.html文件的變更添加到暫存區。
- git add .:將當前目錄下所有未跟蹤和已修改的文件(除了被忽略的文件)添加到暫存區。
暫存區與本地倉庫操作
- git commit -m "commit message":將暫存區的變更提交到本地倉庫,并添加提交信息,用于描述本次提交的內容。例如,git commit -m "添加首頁輪播圖功能"。
本地倉庫與遠程倉庫操作
- git push:將本地倉庫的變更推送到遠程倉庫。在推送前,需要確保本地倉庫與遠程倉庫已關聯,并且當前分支對應遠程的相應分支,例如git push origin main將本地main分支的變更推送到遠程main分支。
- git pull origin <branch>:從遠程倉庫的指定分支拉取變更,并合并到本地倉庫的對應分支。它相當于git fetch和git merge兩個命令的組合。?
- git fetch origin <branch>:從遠程倉庫的指定分支拉取變更,但不會自動合并到本地倉庫的分支,需要手動執行git merge命令進行合并。
各個階段代碼回退
在使用 Git 的過程中,難免會出現需要回退代碼的情況,不同階段的回退方式有所不同:
1. 提交暫存區之前(git add 之前):
- 可以直接在文件中進行修改,丟棄不需要的變更。
- 也可以使用git checkout -- <filename>命令,用本地倉庫中該文件的最新版本覆蓋工作區的文件,從而丟棄工作區的修改。
2. 已經提交到暫存區(git add 之后,git commit 之前):
- 使用git reset HEAD <filename>命令,將暫存區中該文件的變更舍棄,此時可以重新對文件進行修改后再提交到暫存區。
3. 已提交到本地倉庫(git commit 之后):
- 首先使用git log命令查看提交日志,找到想要回退到的提交版本的commit id。
- 然后使用git reset --hard <commit id>命令,將HEAD指針指向指定的版本。
- 如果只是想將工作區的某個文件回退到本地倉庫中某個版本的代碼,可以先通過git reset --hard <commit id>修改本地倉庫HEAD指針指向,然后再使用git checkout -- <filename>命令用本地倉庫的文件覆蓋工作區文件。
4. 已提交到遠程倉庫:
- 首先使用git reset --hard <commit id>命令,將本地倉庫回退到想要的提交版本。
- 此時執行git status會發現本地倉庫分支落后于遠程倉庫分支版本,直接git push無法成功推送,需要使用git push -f命令強制推送,將遠程倉庫的分支也回退到相應版本。需要注意的是,強制推送具有一定的風險,可能會覆蓋其他開發者的提交,在團隊協作中應謹慎使用,最好在推送前與團隊成員溝通。
推送代碼沖突
在合并分支的過程中,當兩個分支對同一個文件的同一部分進行了不同的修改時,就會產生合并沖突。Git 會在沖突的文件中標記出沖突的位置,需要手動解決沖突后再進行提交。解決沖突的步驟如下:?
- 執行git merge命令后,如果出現沖突,Git 會提示哪些文件有沖突。?
- 打開沖突的文件,會看到類似以下的標記:?
<<<<<<< HEAD?當前分支的內容?=======?要合并的分支的內容?>>>>>>> feature/branch?
- 根據實際需求,編輯文件,保留需要的內容,刪除沖突標記和不需要的內容。?
- 編輯完成后,使用git add <file>命令將解決沖突后的文件添加到暫存區。?
- 使用git commit命令提交合并結果。
分支控制
分支是 Git 中非常強大的功能,它允許你在不影響主分支的情況下進行代碼的開發和測試。通過分支,多個開發者可以同時在不同的分支上進行工作,然后將各自的成果合并到主分支。
本地分支控制
- git branch:查看本地所有的分支,當前所在的分支會以*標記。?
- git branch <branch_name>:創建一個新的本地分支,<branch_name>是分支的名稱。例如,git branch feature/login創建一個名為feature/login的分支。?
- git checkout <branch_name>:切換到指定的本地分支。例如,git checkout feature/login切換到feature/login分支。?
- git checkout -b <branch_name>:創建并切換到新的本地分支,相當于git branch <branch_name>和git checkout <branch_name>兩個命令的組合。?
- git merge <branch_name>:將指定的本地分支合并到當前所在的分支。例如,當前在main分支,執行git merge feature/login將feature/login分支的變更合并到main分支。?
- git branch -d <branch_name>:刪除指定的本地分支,需要注意的是,不能刪除當前所在的分支。如果分支還沒有被合并,需要使用git branch -D <branch_name>強制刪除。
遠程分支相關操作
- git branch -r:查看遠程倉庫的所有分支。?
- git push origin <branch_name>:將本地創建的分支推送到遠程倉庫,創建對應的遠程分支。例如,git push origin feature/payment將本地feature/payment分支推送到遠程倉庫,創建遠程feature/payment分支。?
- git checkout -b <local_branch> origin/<remote_branch>:從遠程分支創建一個本地分支,并切換到該本地分支。例如,git checkout -b feature/search origin/feature/search從遠程feature/search分支創建本地feature/search分支。?
- git push origin --delete <branch_name>:刪除遠程倉庫的指定分支。例如,git push origin --delete feature/old刪除遠程feature/old分支。?
- git pull origin <remote_branch>:<local_branch>:將遠程指定分支的變更拉取到本地指定分支。如果本地分支不存在,會自動創建。
Git 實際工作流
在實際的開發工作中,為了保證項目的有序進行,通常會遵循一定的工作流規范。
Git Flow 定義了幾種不同類型的分支,每種分支都有特定的用途:?
- main分支:也稱為master分支,是存放正式發布版本代碼的分支,始終保持穩定可部署的狀態。只有在發布新版本時,才會將develop分支的代碼合并到main分支。?
- develop分支:是開發分支,用于集成各個功能分支的代碼,包含了下一個版本將要發布的功能。團隊成員的功能開發完成后,會將代碼合并到develop分支。?
- feature分支:用于開發新的功能,從develop分支創建,開發完成后合并回develop分支。命名通常以feature/為前綴,例如feature/user-login。?
- release分支:用于版本發布準備,從develop分支創建。在這個分支上只進行 bug 修復和版本相關的配置修改,不添加新功能。發布完成后,將該分支合并到main分支和develop分支。命名通常以release/為前綴,例如release/v1.0.0。?
- hotfix分支:用于修復main分支上的緊急 bug,從main分支創建。修復完成后,將該分支合并到main分支和develop分支。命名通常以hotfix/為前綴,例如hotfix/fix-login-error。?
Git Flow 的工作流程?
- 從main分支創建develop分支,團隊成員基于develop分支進行開發。?
- 當需要開發新功能時,從develop分支創建feature分支,開發者在feature分支上進行功能開發。?
- 功能開發完成后,通過代碼評審,將feature分支合并回develop分支,并刪除feature分支。?
- 當develop分支積累了足夠多的功能,準備發布新版本時,從develop分支創建release分支。?
- 在release分支上進行測試和 bug 修復,確保版本的穩定性。?
- 版本測試通過后,將release分支合并到main分支和develop分支,并在main分支上打上版本標簽(例如v1.0.0),然后刪除release分支。?
- 如果main分支上的正式版本出現緊急 bug,從main分支創建hotfix分支進行修復。?
- 修復完成后,將hotfix分支合并到main分支和develop分支,并在main分支上打上新的版本標簽(例如v1.0.1),然后刪除hotfix分支。?
通過遵循 Git Flow 工作流,團隊可以有條不紊地進行開發、測試和發布,減少代碼沖突和版本管理的混亂,提高開發效率和代碼質量。