項(xiàng)目開發(fā)中g(shù)it是非常重要的,它可以有效、高速地處理從很小到非常大的項(xiàng)目版本管理。
資料:
- 廖雪峰git教程: https://www.liaoxuefeng.com/wiki/896043488029600
- git 筆記: https://github.com/Zhangguoliu/learn-git/blob/master/learngit-note.md
- git 教程: https://git-scm.com/book/zh/v2/Git-基礎(chǔ)-總結(jié)
- git 命令的理解: https://www.yiibai.com/git/git_fetch.html
- git 在線學(xué)習(xí): https://learngitbranching.js.org/?demo
- 了解git flow 協(xié)作開發(fā)理念 : https://www.cnblogs.com/cnblogsfans/p/5075073.html!
項(xiàng)目開發(fā)常用命令
可以設(shè)置當(dāng)前倉庫的 用戶和郵箱
git config --local user.name 'xxx';
git config --local user.email 'xxx';
設(shè)置全局的倉庫大的用戶名和郵箱
git config --global user.name 'xxx';
git config --global user.email 'xxx';
在github提交代碼后貢獻(xiàn)如果沒有被記錄,有可能就是你全局或者當(dāng)前的git倉庫的用戶名和郵箱不是github的用戶名和郵箱。
如果這個(gè)命名存在也可以直接覆蓋修改,還可以替換git config中已有的郵箱
$ git config --global --replace-all user.email "輸入你的郵箱"
$ git config --global --replace-all user.name "輸入你的用戶名"
保存密碼: 如果沒有設(shè)置ssh 可以通過保存密碼的方式來跳過輸入密碼這個(gè)步驟
git config credential.helper store
git stash: https://www.cnblogs.com/zndxall/archive/2018/09/04/9586088.html
本地主分支 :
origin/HEAD -> origin/master表示默認(rèn)分支查看提交詳細(xì)信息:
git showgit status:命令用于顯示工作目錄和暫存區(qū)的狀態(tài)。使用此命令能看到那些修改被暫存到了, 哪些沒有, 哪些文件沒有被Git tracked到。git status不顯示已經(jīng)commit到項(xiàng)目歷史中去的信息。 一般紅色的沒有被追蹤到,綠色的是已經(jīng)add后的, 意思就是被追蹤了克隆指定分支下的內(nèi)容:
clone -b brandName url參看所有分支:
git branch -a 會列出當(dāng)前庫所有的分支(本地、遠(yuǎn)程)切換分支:
git checkout branchName加上 -b 參數(shù)會新建并切換到該分支git checkout -b branchName創(chuàng)建分支:
git brahch branchName刪除分支:
git branch --delete branchName刪除遠(yuǎn)程分支:
git push --delete origin branchName刪除那些遠(yuǎn)程倉庫不存在的分支:
git remote prune origin查看本地分支與遠(yuǎn)程分支的對應(yīng)關(guān)系:
git remote show origin重命名git本地分支:
git branch -m old_local_branch_name new_local_branch_name重命名git遠(yuǎn)程分支:是先刪除遠(yuǎn)程的分支,然后更改本地分支名,然后將更改后的分支推送到遠(yuǎn)程
通過這個(gè)命令可以看出 本地分支與遠(yuǎn)程分支的對應(yīng)關(guān)系,是否與遠(yuǎn)程有對應(yīng)關(guān)系。
Local branches configured for 'git pull':表示本地分支 從哪個(gè)遠(yuǎn)程分支拉取
Local branches configured for 'git pull':表示本地分支 推送到哪個(gè)遠(yuǎn)程分支上去
git 常用命令理解
git fetch
將某個(gè)遠(yuǎn)程主機(jī)的更新 git fetch <遠(yuǎn)程主機(jī)名> 若要更新所有分支,命令可以簡寫為: git fetch
上面命令將某個(gè)遠(yuǎn)程主機(jī)的更新,全部取回本地。默認(rèn)情況下,git fetch取回所有分支的更新。如果只想取回特定分支的更新,可以指定分支名,如下所示: git fetch <遠(yuǎn)程主機(jī)名> <分支名>
比如,取回origin主機(jī)的master分支: git fetch origin master
所取回的更新,在本地主機(jī)上要用遠(yuǎn)程主機(jī)名/分支名的形式讀取。比如origin主機(jī)的master分支,就可以用origin/master讀取。
git branch命令的-r選項(xiàng),可以用來查看遠(yuǎn)程分支,-a選項(xiàng)查看所有分支。
$ git branch -r
origin/master
$ git branch -a
* master
remotes/origin/master
上面命令表示,本地主機(jī)的當(dāng)前分支是master,遠(yuǎn)程分支是origin/master。取回遠(yuǎn)程主機(jī)的更新以后,可以在它的基礎(chǔ)上,使用git checkout命令創(chuàng)建一個(gè)新的分支。
git cherry-pick
場景: 如果你的程序已經(jīng)發(fā)布了一個(gè)版本0.1.1, 代碼分支叫release-0.1.1, 現(xiàn)在正在開發(fā)0.1.x, 我們在開發(fā)分支進(jìn)行后續(xù)的開發(fā),那么有一天產(chǎn)品說, 要把正在開發(fā)的某個(gè)特性(功能)提前上線, 也就是說要把開發(fā)分支上的某些更改移到release-0.1.1的版本上, 那么怎么辦呢?。
思考: 我們的目標(biāo)是:需要把這個(gè)需要發(fā)的功能相關(guān)的代碼移植到想relesase-0.1.1分支上面,這里有一種比較非體力的方法,就是把要發(fā)布的內(nèi)容挑出來,然后移到新的分支(基于relesase-0.1.1拉出來的分支)上去,然后把新的分支合并到relesase-0.1.1。(不能把開發(fā)分支直接合并到relesase-0.1.1)
推薦解決方式: 使用git cherry-pick cherry-pick會重演某些commit, 即把某些commit的更改重新執(zhí)行一遍?;蛘吆唵卫斫膺@里有10次commit提交的內(nèi)容,你可以任意挑選出其中5次commit的內(nèi)容,然后重新執(zhí)行這5次提交(這就是重演)。
- 基于release-2.0分支新建分支release-2.1, 并且到新創(chuàng)建的分支上
git checkout -b release-2.1 release-2.0 - 將dev-3.0分支上的某些commit在release-2.1分支上重演
git cherry-pick dev-3.0分支的某些commit-hash
如:
git cherry-pick
20c2f506d789bb9f041050dc2c1e954fa3fb6910
2633961a16b0dda7b767b9264662223a2874dfa9
5d5929eafd1b03fd4e7b6aa15a6c571fbcb3ceb4
多個(gè)commit-hash使用空格分割, commit-hash最好按提交時(shí)間先后排列, 即最先提交的commit放在前面.
cherry-pick不僅可以用在不同分支之間, 還可以用在同一個(gè)分支上.
不同分支的用法如上所述. 同一分支用法也是一樣的, 同一分支使用情形:
比如說你在某一個(gè)向某個(gè)分支中添加了一個(gè)功能, 后來處于某種原因把它給刪除了,
然而后來某一天你又要添加上這個(gè)功能了, 這時(shí)候就可以使用cherry-pick把添加那個(gè)功能的commit, 再重演一遍.
常見分支操作 -新建分支
情況1 :
如果遠(yuǎn)程新建了一個(gè)分支,本地沒有該分支,可以用 git checkout --track origin/branch_name
這時(shí)候本地會新建一個(gè)分支名叫branch_name,會自動跟蹤(track)遠(yuǎn)程的同名分支branch_name(就可以在這個(gè)本地分支上推拉代碼)
用上面中方法,得到的分支名永遠(yuǎn)和遠(yuǎn)程的分支名一樣,如果想新建一個(gè)本地分支不同名字,同時(shí)跟蹤一個(gè)遠(yuǎn)程分支可以利用。
git checkout -b new_branch_name branch_name
這條指令本來是根據(jù)一個(gè)branch_name分支分出一個(gè)本地分支new_branch_name,但是如果所根據(jù)的分支branch_name是一個(gè)遠(yuǎn)程分支名,那么本地的分支會自動的track遠(yuǎn)程分支。
注意:一般用
git push --set-upstream origin branch_name來在遠(yuǎn)程創(chuàng)建一個(gè)與本地branch_name同名的分支并跟蹤;利用git checkout --track origin/branch_name來在本地創(chuàng)建一個(gè)與branch_name同名分支跟蹤遠(yuǎn)程分支.
當(dāng)使用git checkout -b new_branch_name origin/branch_name當(dāng)提交的時(shí)候會報(bào)這個(gè)錯:
fatal: The upstream branch of your current branch does not match
the name of your current branch. To push to the upstream branch
on the remote, use
git push origin HEAD:master
To push to the branch of the same name on the remote, use
git push origin dev-test
這是由于Git中push.default的設(shè)置的原因
Git中push.default可以指定在沒有明確指定遠(yuǎn)程分支的情況下,默認(rèn)push的遠(yuǎn)程分支,其取值可以是:
nothing-push操作無效,除非顯式指定遠(yuǎn)程分支(意思就是 push的時(shí)候 必須指定遠(yuǎn)程的分支)current-push當(dāng)前分支到遠(yuǎn)程同名分支,如果遠(yuǎn)程同名分支不存在則自動創(chuàng)建同名分支(central 和 non-central workflows都適用)upstream-push當(dāng)前分支到它的upstream分支上(通常用于central workflow)simple-simple和upstream是相似的(通常用于central workflow),只有一點(diǎn)不同,simple必須保證本地分支和它的遠(yuǎn)程upstream分支同名,否則會拒絕push操作matching-push所有本地和遠(yuǎn)程兩端都存在的同名分支-
central / non-central workflows是Git的兩種常見工作流場景:-
central workflows- 集中式工作流,一個(gè)分支的push和pull都是同一個(gè)遠(yuǎn)程倉庫 -
non-central workflows- 非集中式工作流,一個(gè)分支的push和pull可能分別都有不同的遠(yuǎn)程倉庫
-
在Git 2.0之前,push.default的內(nèi)建值被設(shè)為'matching',2.0之后則被更改為了'simple'。
通過git remote show origin可以看到每個(gè)分支的具體信息: (例如 git checkout -b local origin/daily/dev)
Local branches configured for 'git pull':
local merges with remote /daily/dev
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
由于git checkout -b local origin/daily/dev會自動創(chuàng)建遠(yuǎn)程分支/daily/dev 和本地分支local的跟蹤關(guān)系。
其中Local branches configured for 'git pull':下的就是upstream跟蹤分支。
可以看出,遠(yuǎn)程分支/daily/dev和本地分支local建立了git pull的關(guān)系,但是沒有建立git push的關(guān)系。此時(shí)如果強(qiáng)行push,不會成功,會出現(xiàn)如下提示:
fatal: The current branch new has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin develop
這種提示的處理方式下面會給出具體的處理方法。
情況2 :
本地新建分支,然后推送到遠(yuǎn)程,可以使用git branch branch_name或者git checkout -b branch_name(新建并切換到該分支) 新建一個(gè)本地分支,然后修改了代碼 執(zhí)行add 、commit、最后執(zhí)行push操作 發(fā)現(xiàn)會發(fā)現(xiàn)報(bào)錯:
# git push
fatal: The current branch make-scripts-executable has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin branch_name
這是因?yàn)镚it不知道你要提交到哪個(gè)分支上去, 所以需要你指定提交的分支, 直接從本地檢出的新分支,第一次push,遠(yuǎn)程倉庫還沒有與之建立tracing關(guān)系的分支,所以需要設(shè)置upstream,這個(gè)設(shè)置一次之后,后面再push的時(shí)候就不用設(shè)置了。
如果不想這樣寫則需要指定提交到遠(yuǎn)程的分支: git push origin branch_name。
git push origin branch_name推向制定的分支,最強(qiáng)暴的方法。但是每次提交都要指定,太麻煩了(而且還容易出錯)。所以需要與遠(yuǎn)程分支關(guān)聯(lián)。
所以使用git push --set-upstream origin branch_name遠(yuǎn)程分支關(guān)聯(lián)。 這樣就不用每次push的時(shí)候都指定分支了,都會提交到關(guān)聯(lián)的遠(yuǎn)程分支上去。(branch_name是遠(yuǎn)程分支名)
常見分支操作 合并分支
git merge命令用于將兩個(gè)或兩個(gè)以上的開發(fā)歷史加入(合并)一起。 將 merge 后面的分支合并到當(dāng)前分支。
- 將分支dev合并到當(dāng)前分支中,自動進(jìn)行新的提交:
git merge dev
- 合并分支 branch1 和 branch2 在當(dāng)前分支的頂部,使它們合并:
git merge branch1 branch2
- 合并branch1分支到當(dāng)前分支,使用ours合并策略:
git merge -s ours branch1
- 將分支branch1合并到當(dāng)前分支中,但不要自動進(jìn)行新的提交:
git merge --no-commit branch1
Git checkout [文件名]、git reset HEAD [文件名] 、git reset [哈希值] 的應(yīng)用場景。
git reset HEAD [文件名]

通過git reset [文件名] 可以將暫存區(qū)的文件放出來 , 但是我們的工作區(qū)的內(nèi)容沒有改變。只是相當(dāng)于 對[文件名] 不執(zhí)行 git add 操作 。 類似于后退操作。
git checkout [文件名]
工作區(qū)回退:如果比對后,發(fā)現(xiàn)這次改動不是我們想要的,那么我們可以回退到未修改之前,(在vsCode等編輯器里面,可以放棄修改)
git checkout readme.txt
git checkout .
git checkout -- readme.txt // 以防判斷成分支

下面這串?dāng)?shù)字是我們新加的, 通過git status 我們可以看到readme.md文件做了修改

使用 git checkout [文件名] 可以將它變成修改前的是 ,意思就是放棄本次修改。 執(zhí)行改命令后,發(fā)現(xiàn)添加的數(shù)字不見了
git status 顯示文件沒有修改。

如果我們已經(jīng)添加到了暫存區(qū)(意思已經(jīng)執(zhí)行 git add 操作了),如果要退回到修改前,我們應(yīng)該怎么處理呢。
直接通過git checkout [文件名]是不能將它回退到未修改的樣子的??梢韵炔捎?code>git reset HEAD [文件名] 將它移除暫存區(qū)(意思就是回退在沒有執(zhí)行git add 的時(shí)候), 然后通過git checkout [文件名] 將改文件退回到修改前。
git reset [哈希值]
上面的操作都是在暫存區(qū) ,還沒有使用git commit 提交到本地廠庫 。如果已經(jīng)提交到本地廠庫了又要如何操作呢。
將readme.md文件添加一段文字, 然后提交到本地的廠庫。

通過git reflog可以看到一共有兩個(gè)版本 當(dāng)前的版本是HEAD -> master

然后 在修改文件readme.md,然后在提交到本地廠庫。

但是這個(gè)時(shí)候的需求是 回到?jīng)]有添加第二次提交文字的時(shí)候,意思就是要回到上一個(gè)版本。
可以通過使用 git reset 的命令來完成。基本的流程是執(zhí)行:git reset --mixed HEAD^意思就是回退到上一個(gè)版本。

可以發(fā)現(xiàn)命令成功了,是不是頁面也變成了原來的樣子呢,然后并沒有改變。那這個(gè)命令具體做了什么呢?
我們通過看readme.md和git status看可以看到


是將它回退沒有執(zhí)行git add命令之前了,相當(dāng)于你修改了代碼 但是沒有提交的那個(gè)狀態(tài)。然后可以通過git checkout readme.md 命令將它變回未修改的狀態(tài)。
但是如果我們要從現(xiàn)在沒有添加那個(gè)文字的這個(gè)版本 變到添加了文字的版本 要如何操作呢。
通過git reflog 可以看出當(dāng)前的版本是fd8258e

我們使用 git reset --hard HEAD^, 發(fā)現(xiàn)這里readme.md文件直接被修改了。

同時(shí)版本并滅有從fd8258e 變到 a5da32e 而是變到了df0abb9,這里的原因是git的提交是一條時(shí)間線,在這條時(shí)間線上,fd82582的上一次提交就是df0abb9

如果要變成指定的版本應(yīng)該采用命令: git reset [哈希值]; --mixed 為默認(rèn)參數(shù)。

顯示readme.md被修改了,通過左右兩邊的比較可以發(fā)現(xiàn)。 左邊相當(dāng)于原文件,而右邊相當(dāng)于對原文件的修改。可以通過 git checkout readme.md放棄本次修改。

執(zhí)行git checkout readme.md頁面變成了修改之前的,同時(shí)也可以使用git statsu看出沒有做出修改。