本文由Git教學欄位介紹關於Git是如何操作的,非常詳細喲!以下就帶大家一起學習如何玩Git,希望對需要的朋友有幫助!
在某個月黑風高的晚上,一臉愁容的女朋友突然跟我說,Git 老搞不明白,有什麼比較好的經驗可以分享下嗎,說時遲,那時快,二話不說,立刻開始奮筆疾書......
在平時的Coding 過程中,我們還是需要一定的Git 操作的能力的。但總還是存在一些場景自己突然想不起來,某個場景,應該使用什麼Git 命令可以滿足自己的訴求,這個時候又需要打開Google / Baidu,各種搜索一番,與其把時間消磨在這次次的重複工作中,不如好好研究我們常用的指令的玩法。在這裡,本文也將提供一系列的案例,為大家介紹這些常用的 Git 的系統和命令的應用場景以及大體的使用方式。
當然,除了我們需要了解Git 的命令使用方式之外,我們也應該來了解下Git 是的整個體系結構是怎麼樣的,這樣才能更加清晰的知道我們每天操作的命令都是在做什麼。
如有表達不當之處,感謝指正!
開局一張圖,結論先靠猜。
#遠端倉庫區
:也就是我們程式碼最終提交的歸宿,沒啥好說的。 遠端分支本地副本
:這個其實主要儲存了遠端倉庫各分支資料在本地的一個副本,你可以打開你Git 專案下的.git 文件,裡面有個refs /remotes,這裡就主要存的就是遠端倉庫的分支信息,一般你執行push 或者pull、fetch 都會往這裡進行更新。 本地分支
:這裡就是我們經常會打交道的區域,你在執行commit 之後,本質上就是提交到了這個區域,你可以查看你的.git 目錄下的refs/ heads 目錄,裡面存的就是我們本地的分支代碼資訊。 暫存區
:這個區域就是我們每次執行git add 之後會存到的區域,用來與本地倉庫之間做一個緩存,同時也是Git 底層設計上來說也算是比較重要的一個區域,它能幫助Git 在做diff 的時候提高查找效能。 工作區
:這個一般就是我們寫程式碼的地方,像是你的 vscode 開啟的項目,你可以進行程式碼編輯的地方。 除此之外,還有一個特殊的區域,那就是本地的 git 儲存區,它是用來幹嘛的呢?一般來說你可能在某些場景下會用到它,我們有的時候本地改了代碼,但是突然有個人過來問你另一個分支的問題,同時這個時候你在實現某個功能,實現一半,又不想提交到Git 倉庫中,那麼你就可以考慮使用git stash save "暫時存一下"
,這個時候它就會幫你存到這個儲存區,你去其他分支做完事情回來,再git stash pop
就好了。
但筆者還是不是很建議使用這個功能,因為哪天你切走了再切回來,忘記了這個存儲,又寫了點其他的,這個時候你到時候被坑一把就哭吧。當然了,這個功能還是很有用的,但是的確需要細心點用。
日常工作中,我們可能在Git 使用上頻繁互動的流程大致會是這樣的(不同規範下會有一些區別,但是大差不大):
git add
將程式碼提交到暫存區。 git commit
將程式碼提交到本地倉庫git push
將程式碼提交到遠端分支以上流程大致概括了一般常規的 Git flow 流程,不同的公司可能會設計自己的規範,這裡就不過多指示了。
git stash
#git clone
指令解析
git stash(暫時插進來快速介紹一下)
git clone
#有了倉庫之後,我們總不能一直在master 分支搞事吧,一般是不是都需要開個新分支改代碼,再最後完事了再合到master,那就需要用到下面介紹git branch 命令了,不過呢,在講到具體的分支操作之前呢,筆者還是要先補一下有關於本地倉庫的初始化的流程。 git init
不過本地 init 的倉庫沒辦法和遠端進行交互,所以我們還是需要去 github/gitlab 創建一個遠端倉庫,然後關聯一下,也就是
git remotegit remote
git remote add origin xxx.git
先加入到本地倉庫git push -u origin master
:表示把目前倉庫的master 分支和遠端倉庫的master 分支關聯起來,後面我們執行push 或者pull 都可以非常方便的進行操作了。 在拿到一個專案之後,你首先還是應該看一下目前倉庫現在有哪些分支,不要待會建立新分支發現名字重複之類的問題,那這個時候我們就可以使用git branch
來看看相關的分支了。
git branch
:查看本地所有分支資訊#git branch -r
:查看遠端倉庫所有分支git branch -a
:查看本地和遠端倉庫所有分支一般來說如果分支太多的話,還是建議使用視覺化工具來查看分支信息,例如vscode 或者source tree 等軟體等等。
當然 IDEA 也是可以的。
如果我們想以目前分支為基準,建立一個新的分支並切換過去,可以使用以下命令。
git checkout -b branch1
我們在某個分支更改了程式碼之後,想要把它提交一下,那麼你第一步要做的就是,執行git add
#git add [file1] [file2 ]
: 新增一個或多個檔案到暫存區一般我們平常在使用的時候,用的比較多的應該還是:
#git add .
:把目前目錄下得所有檔案改動都加入暫存區git add -A
:把目前倉庫內所有檔案改動都加到暫存區對筆者來說,用的最多的還是這個git add -A 指令,因為大多數情況,我們都應該把所有變更都加到暫存區裡,如果沒有,那大機率是忘了。
檔案加入暫存區之後,我們就可以執行下一步操作了。
git commit [file1] ... -m [message]
:將暫存區的內容提交到本地git 版本倉庫git add - A
,你就不用再add 一下了;對於未被git 管理過的(也就是新增的檔案),那麼還是需要你先執行一下git add -A
,才能正確被commit 到本地git 函式庫。 通常情況下,我們用的比較多到應該是 git commit -m 'feat: do something'
,設定目前提交的資訊。當然,如果你沒有強訴求需要 git add
和 git commit
一定要分開,那你大可選擇 git commit -am
,方便又快捷。
這個其實也蠻有用的,像是我們專案中有個檔案叫.env,這個檔案是一個私有的,不能被提交到遠端的,但是我們不小心提交到了本地倉庫中,這個時候我們把這個檔案加入到.gitignore 檔案中,表示需要被git 忽略提交,但是由於我們已經提交到本地倉庫了,所以如果不先從git 倉庫刪除是沒用的。
如果直接右鍵刪除,那麼這個檔案的記錄還是會被儲存到遠端倉庫,別人還是能看得到你這個訊息,所以我們需要先從 git 倉庫中刪掉這個檔案才行。
git rm .env
:執行完這個指令就表示.env 檔案從git 倉庫中刪除了,配合.gitignore 就能保證以後所有的.env文件變更都不用擔心被提交到遠端倉庫。
git rm -r dist
:如果我們要刪除的是目錄,那麼加上 -r 參數就好了。
接下來我們想要把剛創建好得分支推送到遠端,一般來說我們可能會需要用到git push,但我們這是個新分支,根本沒和遠端倉庫建立任何联系,那麼我們就需要加點參數,讓他們關聯上:
git push -- set-upstream origin branch1
完事之後我們可以再去遠端倉庫看一眼就會發現我們創建的新分支已經推上去了。接下來可能會有小夥伴要問了,那如果遠端倉庫已經有了這個分支名咋整?
這裡就分兩種:
通常情況下,如果目前分支已經和遠端分支建立了聯繫,那麼我們想要合併遠端分支,只需要執行git pull
就好了,不用帶其他參數,但如果和上面提到的git push 時產生了衝突,還沒有建立聯繫的時候,我們就需要指定需要拉取哪個分支的代碼下來進行合併了。
git pull origin branch1
這裡的origin 是我們對遠端倉庫的命名,想改也是可以的,不過一般都是用的origin。
回到上面提到的衝突問題,我們可以直接使用git pull 然後指定合併目前本地分支想要建立聯繫的遠端分支,然後本地解決一下衝突,然後提交改動,再執行git push --set-upstream origin branch1
指令就大功告成了。
了解完上面描述的git pull
,指令之後,其實這個指令也很好理解了,特定時候,可能我們只是想把遠端倉庫對應分支的變更拉到本地而已,並不想自動合併到我的工作區(你目前正在進行代碼變更的工作區),等晚些時候我寫完了某部分的代碼之後再考慮合併,那麼你就可以先使用git fetch
。
fetch 完畢之後,我提交了自己目前工作去的變更到本地倉庫,然後想合併一下遠端分支的更改,這個時候執行一下git merge origin/[目前分支名]
(預設一般是用origin 表示遠端的分支前綴)即可。
合併指定分支程式碼到目前分支。一般來說,我們用的比較多的場景可能是,遠端倉庫master 分支有變更了,同時這個時候我們準備提MR 了,那麼就需要先合一下master 的代碼,有衝突就解決下衝突,那這時候我們可以做以下操作:
同理,上面介紹的git merge origin/xxx 也是一樣的用法。
顧名思義,就是日誌的意思,執行這個命令之後,我們能看到當前分支的提交記錄信息,比如commitId 和提交的時間描述等等,大概長下面這樣:
commit e55c4d273141edff401cbc6642fe21e14681c258 (HEAD -> branch1, origin/branch1) Author: 陌小路 <44311619+STDSuperman@users.noreply.github.com> Date: Mon Aug 1 23:16:11 2022 +0800 Initial commit复制代码
這時候可能有讀者會問了,這個都用來幹啥的,簡單的用法呢就是看看有誰提交了啥,還有更重要的用法呢就是進行代碼版本的回滾,或其他有意思的操作,且聽筆者為你微微道來。
以下解析皆基於後接參數為HEAD^,也就是git reset HEAD^
。
--soft
: 重置你最新提交版本,不會修改你的暫存區和工作區。 --mixed
: 預設參數,用於重置暫存區的檔案與上一次的提交(commit)保持一致,工作區檔案內容保持不變。 --hard
: 重置所有提交到上一個版本,並且修改你的工作區,會徹底回到上一個提交版本,在程式碼中看不到目前提交的程式碼,也就是你的工作區改動也被幹掉了。 說了半天似乎不是很好理解,我們舉個栗子理解下:
例如:
git add
,這個時候你查看暫存區,會發現這次改動被提交進去了,同時被vscode 標記為已被提交至暫存區git commit
,這個時候就完成了一次提交接下來我們想撤回這次提交,以上三種參數所體現的表現會是這樣的:
--soft
:我们对 README 的更改状态现在变成已被提交至暂存区,也就是上面 2 的步骤。--mixed
: 我们对 README 的更改变成还未被提交至暂存区,也就是上面 1 的步骤。--hard
:我们对 README 的所有更改全没了,git log 中也找不到我们对 README 刚刚那次修改的痕迹。默认情况下我们不加参数,就是 --mixed,也就是重置暂存区的文件到上一次提交的版本,文件内容不动。一般会在什么时候用到呢?
可能大部分情况下,比如 vscode 其实大家更习惯于使用可视化的撤销能力,但是呢,这里我们其实也可以稍微了解下这其中的奥秘,其实也很简单:
git reset
git reset HEAD
其实一二都是一样,如果 reset 后面不跟东西就是默认 HEAD。
当你某个改动提交到本地仓库之后,也就是 commit 之后,这个时候你想撤回来,再改点其他的,那么就可以直接使用 git reset HEAD^
。这个时候你会惊奇的发现,你上一版的代码改动,全部变成了未被提交到暂存区的状态,这个时候你再改改代码,然后再提交到暂存区,然后一起再 commit 就可满足你的需求了。
除了这种基础用法,我们还可以配合其他命令操作一下。
某一天你老板跟你说,昨天新加的功能不要了,给我切回之前的版本看看效果,那么这个时候,你可能就需要将工作区的代码回滚到上一个 commit 版本了,操作也十分简单:
git log
查看上一个 commit 记录,并复制 commitIdgit reset --hard commitId
直接回滚。如果某一个你开发需求正开心呢,突然发现,自己以前改的某个东西怎么不见了,你想起来好像是某次合并,没注意被其他提交冲掉了,你心一想,完了,写了那么多,怎么办?很简单,回到有这份代码的那个版本就好了(前提你提交过到本地仓库)。
假设我们有这么两个提交记录,我们需要下面那个 365 开头 commitId 的代码:
commit e62b559633387ab3a5324ead416f09bf347d8e4a (HEAD -> master) Author: xiaohang.lin <xiaohang.lin@alibaba-inc.com> Date: Sun Aug 14 18:08:56 2022 +0800 merge commit 36577ea21d79350845f104eee8ae3e740f19e038 (origin/master, origin/HEAD) Author: 陌小路 <44311619+STDSuperman@users.noreply.github.com> Date: Sun Aug 14 15:57:34 2022 +0800 Update README.md复制代码
git log
找到有你这个代码的那个 commitId(也就是 36577ea21d79350845f104eee8ae3e740f19e038)git reset --hard commitId
这个时候你想把复制好的代码写回去,该怎么办呢,你可能会再 git log 看一下我们 reset 之前的 commitId,你会发现,完了,之前的 commitId 都没了,只有这个 365 了。
commit 36577ea21d79350845f104eee8ae3e740f19e038 (origin/master, origin/HEAD) Author: 陌小路 <44311619+STDSuperman@users.noreply.github.com> Date: Sun Aug 14 15:57:34 2022 +0800 Update README.md复制代码
不要慌,请记住一句话,只要你不删你本地的 .git 仓库,你都能找回以前所有的提交。
git log 看不到的话,我们就可以祭出我们的绝招了:git reflog
36577ea (HEAD -> master, origin/master, origin/HEAD) HEAD@{0}: reset: moving to 36577ea21d79350845f104eee8ae3e740f19e038 e62b559 HEAD@{1}: reset: moving to e62b559633387ab3a5324ead416f09bf347d8e4a复制代码
这里我们可以看到两行记录,一个是我们执行 reset 到 365 的记录,另一条不知道是啥,不重要,我们想回到我们刚刚 reset 之前的状态也很简单,直接复制它上一次的变动也就是这个 e62b559,然后执行 git reset --hard e62b559
,然后你会惊奇的发现,你之前的代码又回来了。
接下来把你以前版本的代码,再 Ctrl + v 放进来就完成了。
介绍:用来查看你的所有操作记录。
既然 git log 看不到我之前 commitId 了,那么就回到 reset 之前的状态吧!
当然了,如果是针对 master 的操作,为了安全起见,一般还是建议使用 revert 命令,他也能实现和 reset 一样的效果,只不过区别来说,reset 是向后的,而 revert 是向前的,怎么理解呢?简单来说,把这个过程当做一次时光穿梭,reset 表示你犯了一个错,他会带你回到没有犯错之前,而 revert 会给你一个弥补方案,采用这个方案之后让你得到的结果和没犯错之前一样。
举个栗子: 假设你改了 README 的描述,新增了一行文字,提交上去了,过一会你觉得这个写了有问题,想要撤销一下,但是又不想之前那个提交消失在当前历史当中,那么你就可以选择使用 git revert [commitId],那么它就会产生一次新的提交,提交的内容就是帮你删掉你上面新增的内容,相当于是一个互补的操作。
PS D:\Code\other\git-practice> git revert 3b18a20ad39eea5264b52f0878efcb4f836931ce On branch branch2 Your branch is ahead of 'origin/branch2' by 1 commit. (use "git push" to publish your local commits)
这个时候,它会提示你可以把新的改动 push 上去了。
其实你如果在 gitlab 进行 mr 之后,想要回滚这个 mr,一般它会给你一个 revert 的按钮选项,让你进行更安全的回滚操作。
其实对于我们工作中大部分场景下应该用不到这个功能,但是呢有的时候这个命令又能挽救你于水火之间,那就是当某个倒霉蛋忘记切分支,然后在 master 分支上改了代码,并且提交到了本地仓库中,这个时候使用git cherry-pick
简直就是神器了。
git cherry-pick
:将执行分支的指定提交合并到当前分支。一听介绍就来精神了,雀氏有点东西,比如我在 master 分支提交了某个需求的代码,同时还没提交到远程分支,那么你就可以先 git log
查看一下当前的提交,找到 master 分支正常提交之后的所有 commitId,然后复制出来,然后再切到你建好的开发分支,接着执行 git cherry-pick master commitId1 commitId2 commitId4
。
完事之后记得清理一下作案现场,把你的 master 分支代码恢复到正常的提交上去。
顾名思义,也就是打标签的意思。一般可能会在你发布了某个版本,需要给当前版本打个标签,你可以翻阅 vite 的官方 git 仓库,查看它的 tag 信息,它这里就标注了各个版本发布时候的 tag 标签。
它有两种标签形式,一种是轻量标签,另一种是附注标签。
git tag v1.0.0
它有点像是对某个提交的引用,从表现上来看,它又有点像基于当前分支提交给你创建了一个不可变的分支,它是支持你直接 checkout 到这个分支上去,但是它和普通分支还是有着本质的区别的,如果你切换到了这个 tag "分支",你去修改代码同时产生了一次提交,亦或者是 reset 版本,这对于该 tag 本身不会有任何影响,而是为你生成了一个独立的提交,但是却在你的分支历史中是找不到的,你只能通过 commitId 来切换到本次提交,看图:
那如果你从其他分支通过 commitId 切换到这个改动上,它会提示你以下内容:
Note: switching to 'be276009'. changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -c with the switch command. Example: git switch -c <new-branch-name> Or undo this operation with: git switch -
大致意思就是你可以选择丢弃或者保留当前更改,如果需要保留的话直接使用下面的 git switch
命令创建一个新分支即可。
git tag -a v1.0.1 -m "发布正式版 1.0.1"
引用官方文档的描述:
而附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。
从概念上看,轻量标签更像是一个临时的标签,而附注标签更加正式一点,能够保留更多的信息。它创建的方式和轻量标签区别主要是 -a 和 -m 参数,如果你的 -m 参数不传,那么编辑器会让你手动填写。
打完标签之后,我们可以使用 git show
命令来看看这两种标签最终体现的信息有哪些。
commit dcbd335be87f51eaa0cc1852400e64e9f46e84d8 (HEAD -> test-branch1, tag: v1.0.2, tag: v1.0.1) Author: STDSuperman <2750556766@qq.com> Date: Tue Aug 16 22:54:36 2022 +0800 xx diff --git a/README.md b/README.md index 715766a..b4cdea6 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@-# git-practice\ No newline at end of file +# git-practice + +test tag
tag v1.0.1 Tagger: STDSuperman <2750556766@qq.com> Date: Tue Aug 16 22:58:27 2022 +0800 发布正式版 1.0.0 commit dcbd335be87f51eaa0cc1852400e64e9f46e84d8 (HEAD -> test-branch1, tag: v1.0.1) Author: STDSuperman <2750556766@qq.com> Date: Tue Aug 16 22:54:36 2022 +0800 xx diff --git a/README.md b/README.md index 715766a..b4cdea6 100644 --- a/README.md +++ b/README.md
从信息丰富度上来说,附注标签能保留的信息会更多。
git push origin tagName
$> git push origin v1.0.1Enumerating objects: 6, done. Counting objects: 100% (6/6), done. Delta compression using up to 12 threads Compressing objects: 100% (3/3), done. Writing objects: 100% (4/4), 448 bytes | 448.00 KiB/s, done. Total 4 (delta 0), reused 0 (delta 0), pack-reused 0 To github.com:STDSuperman/git-practice.git * [new tag] v1.0.1 -> v1.0.1
当然,附注标签和轻量标签都是可以被推送到远端的。
git tag
git tag -l v1.0.1
git tag -d v1.0.1
git push origin --delete v1.0.2
git push origin :refs/tags/v1.0.1
这块其实涉及的玩法会相对来说复杂一点,可能还是需要拿来和 merge 做一下对比才更加有意义,东西有点多,先搁置一下。
WIP...
以上是還沒玩轉Git?立刻安排!的詳細內容。更多資訊請關注PHP中文網其他相關文章!