1. 程式人生 > 其它 >常見Git命令彙總

常見Git命令彙總

前言

最近,有朋友私信讓我就git 使用做篇文章分享,分享一下我在日常工作中是如何使用git的。我當場就收費兩包辣條,最後討價還價,朋友用1.5包辣條騙到了這篇文章,等他欣喜的走了我打算直接分享出來,氣死這個吝嗇鬼,當然最終還是希望本文對你有所幫助。

基礎概念

首先我們簡單的概述一下gitgit有三個分割槽,分別是:

  • 工作區(Working Directory):開發者直接編輯的地方,只要檔案發生了更改,在這就會顯示出來,包含追蹤與未追蹤檔案。通過git add將工作區檔案新增到暫存區。

  • 暫存區(Stage | Index):資料暫時存放的區域,通過git commit將暫存區檔案新增到本地版本庫。

  • 本地版本庫(Local Commit History):存放所有已經提交的資料,通過git push推送到遠端倉庫。

基礎命令

git status

檢視工作區狀態,如果跟蹤的檔案有做任何修改,都可以通過該命令來發現。 如:這裡通過git status就發現在develop分支上,README.md檔案發生了更改。

jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")

git diff

檢視具體修改內容,比如在上一步中,我們通過git status發現README.md檔案發現了更改,這時我們可以通過git diff <file>來檢視具體的修改內容:

jere@JereMBP GitTest (develop) $ git diff README.md
diff --git a/README.md b/README.md
index 7eb4917..3d6d2a4 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
 # GitTest
 For git command practice
+
+do something on develop branch
+
jere@JereMBP GitTest (develop) $ 

另外,你也可以直接使用git diff,這樣就會顯示所有檔案的所有修改內容。

git checkout

切換分支,比如我在feature-1分支上切換到develop分支上:

jere@JereMBP GitTest (feature-1) $ git checkout develop 
Switched to branch 'develop'
jere@JereMBP GitTest (develop) $ 

在當前分支節點上新建一個分支並且切換過去,比如我在 main 分支上建立一個develop新分支並且切換過去:

jere@JereMBP GitTest (main) $ git checkout -b develop
Switched to a new branch 'develop'
jere@JereMBP GitTest (develop) $ git branch
* develop
  main

放棄工作區所作的修改,類似git restore <file>...,比如:我現在想放棄README.md中的修改

jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   README.md
	modified:   dev-file.txt

no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (develop) $ git checkout README.md
Updated 1 path from the index
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   dev-file.txt

no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (develop) $ 

另外,如果你想放棄所有工作區中的修改,可以使用git checkout .來放棄所有修改。

git branch

檢視本地分支情況:

jere@JereMBP GitTest (main) $ git branch
* main

檢視遠端倉庫分支情況:

jere@JereMBP GitTest (develop) $ git branch --remote
  origin/HEAD -> origin/main
  origin/main

在當前節點上建立一個新分支,比如我在 develop 上建立一個feature-1新分支:

jere@JereMBP GitTest (develop) $ git branch feature-1
jere@JereMBP GitTest (develop) $ git branch
* develop
  feature-1
  main

另外,關於建立分支還有一些常用的操作可以瞭解一下,比如:

# 基於某個分支上開出新分支
$ git branch <new-branch> <base-branch>
# 基於某個提交開出新分支
$ git branch <new-branch> commit_hash
# 基於某個tag開出有新分支
$ git branch <new-branch> v1.1

刪除分支

  • 刪除本地分支:git branch -d <branch-name>
  • 刪除遠端分支:git push -d origin <branch-name>

git add

將工作區所作的修改新增到暫存區,如將README.md檔案新增到暫存區:

jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (develop) $ git add README.md
jere@JereMBP GitTest (develop) $ git status
On branch develop
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   README.md

jere@JereMBP GitTest (develop) $ 

另外,你也可以通過git add .命令,這會將工作區所有的修改內容都新增到暫存區。

git commit

將暫存區中的內容儲存到本地工作區,如上一步我們已經將README.md檔案新增到了暫存區,接下來就將它儲存到本地工作區:

jere@JereMBP GitTest (develop) $ git commit -m "更改README檔案"
[develop b18e4f1] 更改README檔案
 1 file changed, 3 insertions(+)
jere@JereMBP GitTest (develop) $ git status
On branch develop
nothing to commit, working tree clean
jere@JereMBP GitTest (develop) $ 

另外,你也可以通過git commit -am來進行快速操作,其實它就是git add . & git commit -m的結合體。

git push

將本地檔案推送到遠端倉庫中,如:將上一步已經儲存到本地的README.md檔案推送到遠端倉庫:

jere@JereMBP GitTest (develop) $ git push origin develop 
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 371 bytes | 371.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/JereChen11/GitTest.git
   1f7fb80..b18e4f1  develop -> develop
jere@JereMBP GitTest (develop) $ 

git fetch

檢視遠端倉庫有沒有更新,有更新就下載下來,如果沒有更新就沒有任何反應,如:這裡通過git fetch發現遠端倉庫中main分支有了新提交,所以將其下載了下來。

jere@JereMBP GitTest (develop) $ git fetch 
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/JereChen11/GitTest
   30f049e..d6ff31d  main       -> origin/main
jere@JereMBP GitTest (develop) $ git fetch 
jere@JereMBP GitTest (develop) $ 

git merge

合併分支,如:在上一步中,我們通過git fetch發現遠端 mian 分支有了新提交,所以當前本地main分支是落後的,所以這時候我們就應該將遠端 mian 分支合併到我們的本地main分支,來實現兩端同步。

jere@JereMBP GitTest (develop) $ git checkout main
Switched to branch 'main'
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
  (use "git pull" to update your local branch)
jere@JereMBP GitTest (main) $ git merge origin/main 
Updating 30f049e..d6ff31d
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)
jere@JereMBP GitTest (main) $ 

git pull

拉取遠端倉庫,如果遠端倉庫有更新,則會將更新下載下來併合併到當前分支上,相當於git fetchgit merge的結合體。 如:跟上一步同樣,這次我們使用git pull來拉取遠端 mian 分支上的新提交。

jere@JereMBP GitTest (main) $ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/JereChen11/GitTest
   55e808c..4a1a531  main       -> origin/main
Updating 55e808c..4a1a531
Fast-forward
 README.md | 2 ++
 1 file changed, 2 insertions(+)

業務場景

除了上面幾個基礎命令,現在我根據我們平時的業務場景,配合案例再介紹幾個指令。

解決衝突

關於衝突,一旦涉及分支合併,且這兩個分支有對同一個地方做更改,就會出現衝突。

比如:在上一步中我們將遠端mian分支拉取了下來,發現他是對README.md檔案做了更改,而我們一開始的時候已經在develop分支上對README.md檔案相同位置上做了更改,這時候,如果我們嘗試將develop合併到main分支上時,就會出現衝突。

jere@JereMBP GitTest (main) $ git merge develop 
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
jere@JereMBP GitTest (main) $ git status
On branch main
Your branch is up to date with 'origin/main'.

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
	new file:   dev-file.txt

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   README.md

jere@JereMBP GitTest (main) $ 

正是README.md檔案發生了衝突,我們需要開啟該檔案來檢視具體衝突內容。

# GitTest
For git command practice

<<<<<<< HEAD
chagne README file on the main branch //內容1
=======
do something on develop branch //內容2
>>>>>>> develop

衝突的內容會被<<<<<<<>>>>>>>所包圍,中間用=======隔離開,也就如我所註釋的分成了內容1內容2兩塊。

  • 內容1:是當前所在分支節點的內容,也就是mian
  • 內容2:要合併進來分支的內容,也就是develop

選擇你要的內容,將<<<<<<<>>>>>>>=======這些隔離符刪除掉,並儲存,然後執行git addgit commit完成合並。

jere@JereMBP GitTest (main) $ vim README.md 
jere@JereMBP GitTest (main) $ git status
On branch main
Your branch is up to date with 'origin/main'.

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
	new file:   dev-file.txt

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   README.md

jere@JereMBP GitTest (main) $ git commit -am "解決README衝突"
[main 8e08c23] 解決README衝突
jere@JereMBP GitTest (main) $ 

組員間同步開發進度

在實際專案中,我們都是多人配合協同開發,會將一些需求進行拆分,然後大家同時開發,開發完成後,各自將自己的程式碼合併到develop分支上。 在這過程中,如果某個組員已經開發完了並且將程式碼合併到了develop分支,而你還沒開發完,但是這時你想同步這個組員的程式碼,這時應該怎麼做呢?

這裡我們就可以使用git rebase來做到。

git rebase操作,稱之為變基操作,也就是移動你的分支的根節點。

舉個例子:

  1. feature-1feature-2 都是基於 develop 同一節點開出來的分支。
  2. 隨著開發的進行,feature-1先開發完成,併合併到develop分支。
  3. 此時feature-2利用 git rebase origin develop 來同步feature-1的程式碼。
jere@JereMBP GitTest (feature-2) $ git rebase origin/develop 
First, rewinding head to replay your work on top of it...
Applying: 新增 feature-22.txt 檔案
Applying: 修改feature-22.txt
jere@JereMBP GitTest (feature-2) $ 

這三個狀態的節點分支情況如下圖所示:

初始狀態 feature-1合併到develop feature-2同步develop程式碼

整理合並提交

有時候,我們想對自己的提交進行合併操作。

我們可以通過git rebase -i HEAD~x 來合併(這裡 i 的意思為interactive互動,HEAD~x代表要合併HEAD到前x個歷史提交,如: HEAD~2為歷史的前兩個提交,HEAD~4就是歷史的前四個提交)。

舉個例子: 我們在feature-3分支上對feature-3.txt進行了兩次提交修改,分別是598cc68 修改feature-3.txt8561ef3 再次修改feature-3.txt,現在我們要將這兩個提交進行合併

  1. 執行 git rebase -i HEAD~2
  2. 這是會自動進入vim,顯示如下內容:
pick 598cc68 修改feature-3.txt
pick 8561ef3 再次修改feature-3.txt
...省略...


這裡我們要合併這兩個提交,所以將第二個pick更改為s,如下:

pick 598cc68 修改feature-3.txt
s 8561ef3 再次修改feature-3.txt
...省略...


儲存退出,將自動開啟另外一個vim檔案,用來修改提交文字資訊,如下:

# This is a combination of 2 commits.
# This is the 1st commit message:

修改feature-3.txt
# This is the commit message #2:

再次修改feature-3.txt
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#


這裡我們將其修改為最終版本,修改feature-3.txt,儲存退出。

jere@JereMBP GitTest (feature-3) $ git rebase -i HEAD~2
[detached HEAD 18296c5] 最終版本,修改feature-3.txt
 Date: Wed Dec 1 10:21:05 2021 +0800
 1 file changed, 2 insertions(+)
Successfully rebased and updated refs/heads/feature-3.
jere@JereMBP GitTest (feature-3) $

  1. 此時,你本地分支已經完成了合併,你嘗試將其推送到倉庫中時,會發現被拒絕。通過提示可知,拒絕理由是our current branch is behind 你當前分支落後遠端分支,這時,我們需要 git push origin feature-3 -f強制推送,完成合並。
jere@JereMBP GitTest (feature-3) $ git push origin feature-3 
To https://github.com/JereChen11/GitTest.git
 ! [rejected]        feature-3 -> feature-3 (non-fast-forward)
error: failed to push some refs to 'https://github.com/JereChen11/GitTest.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
jere@JereMBP GitTest (feature-3) $ git push origin feature-3 -f
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 356 bytes | 356.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/JereChen11/GitTest.git
 + 8561ef3...18296c5 feature-3 -> feature-3 (forced update)

這三個狀態的節點分支情況如下圖所示:

執行 git rebase -i HEAD~2 採用squash合併提交,並修改文字資訊 強制推送到倉庫

還記得我們將 pick 改為 s 這一步嗎?這裡的s指的是squash,意思是將該提交擠壓合併到上一個提交。 他還有一些其它選項操作可以瞭解一下:

p, pick <commit> = 使用提交
r, reword <commit> = 使用提交,但是會編輯提交文字資訊
e, edit <commit> = 使用提交,在修改完成後,可以通過git commit --amend再次進行修改;修改滿意後再使用git rebase --continue
s, squash <commit> = 使用提交,擠壓合併到上一個提交
f, fixup <commit> = 類似"squash",會擠壓合併到上一個提交,但是會忽略修改提交文字資訊這一步。

整理提交的必要性 如果你的分支上存在這樣的情況:提交1:finish login feature,緊接著後面就是提交2:code review for login feature。 這樣的操作其實很正常,也很合理,你在做好功能後,去做了code review,但其實我們完全可以將這兩個提交合併成一個提交,方便自己以及同事檢視你的程式碼。

注意:你要在你自己的分支進行操作。

撤銷提交

這邊撤銷提交分為撤銷本地提交撤銷遠端提交

撤銷本地提交

當你提交了程式碼到本地,但此時,你想撤回這個提交,重新編輯修改一下。這時你可以通過 git reset 來實現。

這個撤銷分為是否保留修改

  • 保留修改:git reset --soft,你之前所作的更改都在,這也稱為最安全的撤銷。
  • 捨棄修改:git reset --hard,你之前所作的更改都會消失,所以要謹慎使用。

舉個例子: 當前你處於feature-4分支上,你提了一個本地提交第二次修改,這時你想撤銷回來繼續修改。

jere@JereMBP GitTest (feature-4) $ git reset --soft HEAD~

如果,我直接不要這個第二次修改本地提交,則:

jere@JereMBP GitTest (feature-4) $ git reset --hard HEAD~
HEAD is now at 16960c7 第一次修改

這三個狀態的節點分支情況如下圖所示:

初始狀態 git revert --soft git revert --hard

撤銷遠端提交(回滾操作)

當你將你的本地提交推送到了遠端倉庫中,這時,你發現你完全做錯了,你想進行回滾操作。

這時你就需要用到git revert操作。

舉個例子: 我在feature-4分支上提了兩個提交且都推送到了倉庫,分別是第一次修改第二次修改,現在我想進行回滾操作,撤銷第二次修改這個提交。

jere@JereMBP GitTest (feature-4) $ git revert HEAD
[feature-4 c73e361] Revert "第二次修改"
 1 file changed, 1 deletion(-)

執行命令後,會自動開啟一個vim檔案來讓你修改提交文字資訊,預設在開頭加上revert 修飾,儲存退出,操作結束。

撤銷前後這兩個狀態的節點分支情況如下圖所示:

撤銷前 撤銷後

如圖所示,回滾操作後,會多一個revert xxx提交,如果你不想要這個提交,不想讓人知道你進行了回滾,你可以使用上面介紹的git rebase -i HEAD~x進行整理合並提交。

另外,你也可以通過git revert <commit_hash>來對指定提交進行回滾,如果遇到衝突就先解決衝突,然後執行git revert --continue繼續。

注意:執行回滾操作需要注意環境,如果別人拉了你的程式碼,這時你再執行回滾操作,那就不好了。

線上出Bug了,緊急修復

講個故事吧。

經過一段時間的開發,你們的產品終於上線了,版本為V1.0,產品上線後你馬上投入到了V1.1版本的需求開發。某天,運營與產品同時過來找你,說剛剛發現線上存在一個很嚴重的bug,需要緊急修復一下。你馬上投入修復工作,經過緊張的排查與測試,最終你修復了這個問題,準備發版。 而此時,你才注意到,你是在develop分支上進行的修復工作,而develope分支已經包含了v1.1的部分功能,這時,怎麼把這個緊急修復提交給到V1.0呢?

可以通過git cherry-pick做到,翻譯為挑選的意思,將某個提交挑選過來。

如:我們現在要將develop分支上的d818f10 緊急修復線上bug這個提交合併到我們main V1.0上。先切換到main分支上,然後將d818f10這個提交挑選過來合併。

jere@JereMBP GitTest (develop) $ git co main 
Switched to branch 'main'
Your branch is up to date with 'origin/main'.
jere@JereMBP GitTest (main) $ git cherry-pick d818f10
[main 55e808c] 緊急修復線上bug
 Date: Wed Dec 1 15:49:48 2021 +0800
 1 file changed, 2 insertions(+)

這三個狀態的節點分支情況如下圖所示:

初始狀態 develop上修復 將這個修復提交挑選到main

暫時儲存手頭工作

某天你正在認真的開發需求中,測試過來找你讓你幫忙看一個線上問題。此時,你程式碼也剛寫了一半,不想提交,這時怎麼辦?

此時我們可以通過git stash來暫存我們程式碼,然後切換到線上環境分支排查問題,解決後,切換回之前分支執行git stash pop繼續開發。

如:我現在正在feature-5分支上開發新需求,此時我需要暫存所有更改,切換到main分支排查問題。排查結束,回到feature-5,將暫存取出,繼續開發。

jere@JereMBP GitTest (feature-5) $ git status
On branch feature-5
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   feature-5.txt

no changes added to commit (use "git add" and/or "git commit -a")
jere@JereMBP GitTest (feature-5) $ git stash
Saved working directory and index state WIP on feature-5: 9bd4e1f 新增 feature-5.txt
jere@JereMBP GitTest (feature-5) $ git status
On branch feature-5
nothing to commit, working tree clean
jere@JereMBP GitTest (feature-5) $ git stash pop
On branch feature-5
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   feature-5.txt

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (1ec48d00e8d1bd5c0042d88d1209dbb9051815d4)
jere@JereMBP GitTest (feature-5) $ 

另外,git stash 還有一些常用操作。

# 儲存到stash棧中,並加上自定義message修飾
$ git stash save "message"
# 列出stash棧中所有元素
$ git stash list
# 應用stash棧中的第x個元素,pop是應用的同時且從棧中刪除,而apply則是隻應用不刪除
$ git stash apply stash@{x}
# 刪除stash棧中的第x個元素
$ git stash drop stash@{x}

上線發版啦

當我們產品開發完成,發現上線時,我們需要打個標籤來標註一下,以便下次更好的找它。

這時我們就可以通過git tag 標籤名來打標籤。

舉個例子:我們的1.0版本上線了,所以打個v1.0

jere@JereMBP GitTest (feature-5) $ git tag v1.0
jere@JereMBP GitTest (feature-5) $ git tag
v1.0
v1.0.1

另外,關於tag的一些其它操作有:

# 檢視所有標籤
$ git tag
# 刪除指定tag
$ git tag -d 標籤名

修改最近提交的文字資訊

很多時候,我們提交的時候,可能會輸錯提交的文字資訊,然後想修改一下。

這時,你可以通過git commit --amend來修改最近的提交的文字訊息

當然,你也可以通過剛剛介紹的撤銷本地提交做到,這邊就不再次展示了。

git config 一些配置

通過git config --list來檢視你的git配置資訊

配置別名

每次輸入我們都需要輸入完整的checkoutcommit,很麻煩,我們可以通過設定別名來實現。

$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

設定完成後,你在通過git config --list檢視配置,就會發現:

alias.co=checkout
alias.br=branch
alias.ci=commit
alias.st=status

之後你就可以通過git co <branch>git st來切換分支、檢視狀態了..

配置代理

因為一些特殊網路原因,我們很多時候上github很不穩定,有時候我們推送一些程式碼會403失敗。這時我們就可以通過設定代理來解決。

比如:我們設定一個本地代理。

git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080
git config --global http.proxy 'socks5://127.0.0.1:1080'
git config --global https.proxy 'socks5://127.0.0.1:1080'

設定完成後,你再通過git config --list檢視配置,就會發現:

http.proxy=http://127.0.0.1:1080
https.proxy=https://127.0.0.1:1080

設定代理成功後,某天,你想取消該代理,這時我們可以通過unset來取消代理設定。

git config --global --unset http.proxy
git config --global --unset https.proxy

結尾:

OK,文章到此也就結束啦。

建議對git命令還不太熟練的同學多上手試試,遇到問題不要慌,注意看它給的提示,相信很快就能掌握啦。

其實分享文章的最大目的正是等待著有人指出我的錯誤,如果你發現哪裡有錯誤,請毫無保留的指出即可,虛心請教。 另外,如果你覺得文章不錯,對你有所幫助,請給我點個贊,就當鼓勵,謝謝 ~Peace~!

轉自:Jere_Chen