1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        三年 Git 使用心得 & 常見問題整理

        共 19482字,需瀏覽 39分鐘

         ·

        2020-08-03 11:15


        來源:https://juejin.im/post/5ee649ff51882542ea2b5108

        Git 流程圖

        • Workspace:工作區(qū)
        • Index / Stage:暫存區(qū)
        • Repository:倉庫區(qū)(或本地倉庫)
        • Remote:遠程倉庫

        配置 Git

        # 配置全局用戶
        $ git config --global user.name "用戶名"
        $ git config --global user.email "git賬號"
        # 配置別名
        $ git config --global alias.co checkout
        $ git config --global alias.ss status
        $ git config --global alias.cm commit
        $ git config --global alias.br branch
        $ git config --global alias.rg reflog
        # 這里只是美化 log 的輸出,實際使用時可以在 git lg 后面加命令參數(shù),如:git lg -10 顯示最近10條提交
        $ git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
        # 刪除全局配置
        $ git config --global --unset alias.xxx
        $ git config --global --unset user.xxx

        查看 Git 信息

        # 查看系統(tǒng)配置
        $ git config --list
        # 查看用戶配置
        $ cat ~/.gitconfig
        # 查看當前項目的 git 配置
        $ cat .git/config
        # 查看暫存區(qū)的文件
        $ git ls-files
        # 查看本地 git 命令歷史
        $ git reflog
        # 查看所有 git 命令
        $ git --help -a
        # 查看當前 HEAD 指向
        $ cat .git/HEAD

        # git 中 D 向下翻一行 F 向下翻頁 B 向上翻頁 Q 退出
        # 查看提交歷史
        $ git log --oneline
        --grep="關(guān)鍵字"
        --graph
        --all
        --author "username"
        --reverse
        -num
        -p
        --before= 1 day/1 week/1 "2019-06-06"
        --after= "2019-06-06"
        --stat
        --abbrev-commit
        --pretty=format:"xxx"

        # oneline -> 將日志記錄一行一行的顯示
        # grep="關(guān)鍵字" -> 查找日志記錄中(commit提交時的注釋)與關(guān)鍵字有關(guān)的記錄
        # graph -> 記錄圖形化顯示 !?。?br># all -> 將所有記錄都詳細的顯示出來
        # author "username" -> 查找這個作者提交的記錄
        # reverse -> commit 提交記錄順序翻轉(zhuǎn)
        # before -> 查找規(guī)定的時間(如:1天/1周)之前的記錄
        # num -> git log -10 顯示最近10次提交 ?。?!
        # stat -> 顯示每次更新的文件修改統(tǒng)計信息,會列出具體文件列表 !?。?br># abbrev-commit -> 僅顯示 SHA-1 的前幾個字符,而非所有的 40 個字符 ?。?!
        # pretty=format:"xxx" -> 可以定制要顯示的記錄格式 !??!
        # p -> 顯示每次提交所引入的差異(按 補丁 的格式輸出)!??!

        git reflog

        • 「顯示的是一個 HEAD 指向發(fā)生改變的時間列表」。在你切換分支、用 git commit 進行提交、以及用 git reset 撤銷 commit 時,HEAD 指向會改變,但當你進行 git checkout -- 撤銷或者 git stash ?存儲文件等操作時,HEAD 并不會改變,這些修改從來沒有被提交過,因此 reflog 也無法幫助我們恢復它們。
        • git reflog 不會永遠保持,Git 會定期清理那些 “用不到的” 對象,不要指望幾個月前的提交還一直在那里。

        git log 點線圖

        • 「git 中一條分支就是一個指針,新建一條分支就是基于當前指針新建一個指針」
        • 「切換至某個分支 ,就是將 HEAD 指向某條分支(指針)」
        • 「切換至某個 commit ,就是將 HEAD 指向某個 commit」

        符號解釋:

        *	表示一個 commit
        | 表示分支前進
        / 表示分叉
        \ 表示合入
        |/ 表示新分支

        Git 常用命令

        # 查看工作區(qū)和暫存區(qū)的狀態(tài)
        $ git status
        # 將工作區(qū)的文件提交到暫存區(qū)
        $ git add .
        # 提交到本地倉庫
        $ git commit -m "本次提交說明"
        # add和commit的合并,便捷寫法(未追蹤的文件無法直接提交到暫存區(qū)/本地倉庫)
        $ git commit -am "本次提交說明"
        # 將本地分支和遠程分支進行關(guān)聯(lián)
        $ git push -u origin branchName
        # 將本地倉庫的文件推送到遠程分支
        $ git push
        # 拉取遠程分支的代碼
        $ git pull origin branchName
        # 合并分支
        $ git merge branchName
        # 查看本地擁有哪些分支
        $ git branch
        # 查看所有分支(包括遠程分支和本地分支)
        $ git branch -a
        # 切換分支
        $ git checkout branchName
        # 臨時將工作區(qū)文件的修改保存至堆棧中
        $ git stash
        # 將之前保存至堆棧中的文件取出來
        $ git stash pop

        Git 常用命令詳解

        add

        將工作區(qū)的文件添加到暫存區(qū)

        # 添加指定文件到暫存區(qū)(追蹤新增的指定文件)
        $ git add [file1] [file2] ...
        # 添加指定目錄到暫存區(qū),包括子目錄
        $ git add [dir]
        # 添加當前目錄的所有文件到暫存區(qū)(追蹤所有新增的文件)
        $ git add .
        # 刪除工作區(qū)/暫存區(qū)的文件
        $ git rm [file1] [file2] ...
        # 停止追蹤指定文件,但該文件會保留在工作區(qū)
        $ git rm --cached [file]
        # 改名工作區(qū)/暫存區(qū)的文件
        $ git mv [file-original] [file-renamed]

        # Git 2.0 以下版本
        #只作用于文件的新增和修改
        $ git add .
        #只作用于文件的修改和刪除
        $ gti add -u
        #作用于文件的增刪改
        $ git add -A

        # Git 2.0 版本
        $ git add . 等價于 $ git add -A

        • git add .「操作的對象是“當前目錄”所有文件變更」,"." ?表示當前目錄。會監(jiān)控工作區(qū)的狀態(tài)樹,使用它會把工作區(qū)的「所有變化提交」到暫存區(qū),包括文件內(nèi)容修改(modified)以及新文件(new),但「不包括被刪除的文件」。
        • git add -u「操作的對象是整個工作區(qū)已經(jīng)跟蹤的文件變更,無論當前位于哪個目錄下」。僅監(jiān)控「已經(jīng)被 add 的文件」(即 tracked file),它會將被修改的文件(包括文件刪除)提交到暫存區(qū)。git add -u 不會提交新文件(untracked file)。(git add --update 的縮寫)
        • git add -A「操作的對象是“整個工作區(qū)”所有文件的變更,無論當前位于哪個目錄下」。是上面兩個功能的合集(git add --all 的縮寫)。

        status

        # 查看工作區(qū)和暫存區(qū)的狀態(tài)
        $ git status

        commit

        # 將暫存區(qū)的文件提交到本地倉庫并添加提交說明
        $ git commit -m "本次提交的說明"

        # add 和 commit 的合并,便捷寫法
        # 和 git add -u 命令一樣,未跟蹤的文件是無法提交上去的
        $ git commit -am "本次提交的說明"

        # 跳過驗證繼續(xù)提交
        $ git commit --no-verify
        $ git commit -n

        # 編輯器會彈出上一次提交的信息,可以在這里修改提交信息
        $ git commit --amend
        # 修復提交,同時修改提交信息
        $ git commit --amend -m "本次提交的說明"
        # 加入 --no-edit 標記會修復提交但不修改提交信息,編輯器不會彈出上一次提交的信息
        $ git commit --amend --no-edit

        • git commit --amend 既可以修改上次提交的文件內(nèi)容,也可以修改上次提交的說明。會用一個新的 commit 更新并替換最近一次提交的 commit 。如果暫存區(qū)有內(nèi)容,這個新的 commit 會把任何修改內(nèi)容和上一個 commit 的內(nèi)容結(jié)合起來。如果暫存區(qū)沒有內(nèi)容,那么這個操作就只會把上次的 commit 消息重寫一遍。「永遠不要修復一個已經(jīng)推送到公共倉庫中的提交,會拒絕推送到倉庫」

        push & pull

        • 分支推送順序的寫法是 「<來源地>:<目的地>」
        # 將本地倉庫的文件推送到遠程分支
        # 如果遠程倉庫沒有這個分支,會新建一個同名的遠程分支
        # 如果省略遠程分支名,則表示兩者同名
        $ git push <遠程主機名> <本地分支名>:<遠程分支名>
        $ git push origin branchname

        # 如果省略本地分支名,則表示刪除指定的遠程分支
        # 因為這等同于推送一個空的本地分支到遠程分支。
        $ git push origin :master
        # 等同于
        $ git push origin --delete master

        # 建立當前分支和遠程分支的追蹤關(guān)系
        $ git push -u origin master
        # 如果當前分支與遠程分支之間存在追蹤關(guān)系
        # 則可以省略分支和 -u
        $ git push

        # 不管是否存在對應的遠程分支,將本地的所有分支都推送到遠程主機
        $ git push --all origin

        # 拉取所有遠程分支到本地鏡像倉庫中
        $ git pull
        # 拉取并合并項目其他人員的一個分支
        $ git pull origin branchname
        # 等同于 fetch + merge
        $ git fetch origin branchName
        $ git merge origin/branchName

        # 如果遠程主機的版本比本地版本更新,推送時 Git 會報錯,要求先在本地做 git pull 合并差異,
        # 然后再推送到遠程主機。這時,如果你一定要推送,可以使用 –-force 選項
        # (盡量避免使用)
        $ git push --force origin | git push -f origin

        branch

        # 查看本地分支
        $ git branch | git branch -l
        # 查看遠程分支
        $ git branch -r
        # 查看所有分支(本地分支+遠程分支)
        $ git branch -a
        # 查看所有分支并帶上最新的提交信息
        $ git branch -av
        # 查看本地分支對應的遠程分支
        $ git branch -vv

        # 新建分支
        # 在別的分支下新建一個分支,新分支會復制當前分支的內(nèi)容
        # 注意:如果當前分支有修改,但是沒有提交到倉庫,此時修改的內(nèi)容是不會被復制到新分支的
        $ git branch branchname
        # 切換分支(切換分支時,本地工作區(qū),倉庫都會相應切換到對應分支的內(nèi)容)
        $ git checkout branchname
        # 創(chuàng)建一個 aaa 分支,并切換到該分支 (新建分支和切換分支的簡寫)
        $ git checkout -b aaa
        # 可以看做是基于 master 分支創(chuàng)建一個 aaa 分支,并切換到該分支
        $ git checkout -b aaa master

        # 新建一條空分支(詳情請看問題列表)
        $ git checkout --orphan emptyBranchName
        $ git rm -rf .

        # 刪除本地分支,會阻止刪除包含未合并更改的分支
        $ git brnach -d branchname
        # 強制刪除一個本地分支,即使包含未合并更改的分支
        $ git branch -D branchname
        # 刪除遠程分支
        # 推送一個空分支到遠程分支,其實就相當于刪除遠程分支
        $ git push origin :遠程分支名
        # 或者
        $ git push origin --delete 遠程分支名

        # 修改當前分支名
        $ git branch -m branchname

        merge 三種常用合并方法

        # 默認 fast-forward ,HEAD 指針直接指向被合并的分支
        $ git merge

        # 禁止快進式合并
        $ git merge --no-ff

        $ git merge --squash

        • fast-forward:會在當前分支的提交歷史中添加進被合并分支的提交歷史(「得先理解什么時候會發(fā)生快速合并,并不是每次 merge 都會發(fā)生快速合并」);
        • --no-ff「會生成一個新的提交」,讓當前分支的提交歷史不會那么亂;
        • --squash「不會生成新的提交」,會將被合并分支多次提交的內(nèi)容直接存到工作區(qū)和暫存區(qū),由開發(fā)者手動去提交,這樣當前分支最終只會多出一條提交記錄,不會摻雜被合并分支的提交歷史

        rebase

        www.liaoxuefeng.com/wiki/896043…

        git-scm.com/book/zh/v2/…

        www.jianshu.com/p/4a8f4af4e…

        juejin.im/post/5a5438…

        stash

        • 能夠?qū)⑺形刺峤坏男薷谋4嬷炼褩V?,用于后續(xù)恢復當前工作區(qū)內(nèi)容
        • 如果文件沒有提交到「暫存區(qū)(使用 git add . 追蹤新的文件)」,使用該命令會提示 No local changes to save ,無法將修改保存到堆棧中

        「使用場景:」 當你接到一個修復緊急 bug 的任務(wù)時候,一般都是先創(chuàng)建一個新的 bug 分支來修復它,然后合并,最后刪除。但是,如果當前你正在開發(fā)功能中,短時間還無法完成,無法直接提交到倉庫,這時候可以先把當前工作區(qū)的內(nèi)容 git stash 一下,然后去修復 bug,修復后,再 git stash pop,恢復之前的工作內(nèi)容。

        # 將所有未提交的修改(提交到暫存區(qū))保存至堆棧中
        $ git stash
        # 給本次存儲加個備注,以防時間久了忘了
        $ git stash save "存儲"
        # 存儲未追蹤的文件
        $ git stash -u

        # 查看存儲記錄
        $ git stash list

        在 Windows 上和 PowerShell 中,需要加雙引號
        # 恢復后,stash 記錄并不刪除
        $ git stash apply "stash@{index}"
        # 恢復的同時把 stash 記錄也刪了
        $ git stash pop "stash@{index}"
        # 刪除 stash 記錄
        $ git stash drop "stash@{index}"
        # 刪除所有存儲的進度
        $ git stash clear
        # 查看當前記錄中修改了哪些文件
        $ git stash show "stash@{index}"
        # 查看當前記錄中修改了哪些文件的內(nèi)容
        $ git stash show -p "stash@{index}"

        diff

        # 查看工作區(qū)和暫存區(qū)單個文件的對比
        $ git diff filename
        # 查看工作區(qū)和暫存區(qū)所有文件的對比
        $ git diff
        # 查看工作區(qū)和暫存區(qū)所有文件的對比,并顯示出所有有差異的文件列表
        $ git diff --stat
        # 注意:
        # 1.你修改了某個文件,但是沒有提交到暫存區(qū),這時候會有對比的內(nèi)容
        # 一旦提交到暫存區(qū),就不會有對比的內(nèi)容(因為暫存區(qū)已經(jīng)更新)
        # 2.如果你新建了一個文件,但是沒有提交到暫存區(qū),這時候 diff 是沒有結(jié)果的

        # 查看暫存區(qū)與上次提交到本地倉庫的快照(即最新提交到本地倉庫的快照)的對比
        $ git diff --cached/--staged
        # 查看工作區(qū)與上次提交到本地倉庫的快照(即最新提交到本地倉庫的快照)的對比
        $ git diff branchname
        # 查看工作區(qū)與 HEAD 指向(默認當前分支最新的提交)的對比
        $ git diff HEAD

        # 查看兩個本地分支中某一個文件的對比
        $ git diff branchname..branchname filename
        # 查看兩個本地分支所有的對比
        $ git diff branchname..branchname
        # 查看遠程分支和本地分支的對比
        $ git diff origin/branchname..branchname
        # 查看遠程分支和遠程分支的對比
        $ git diff origin/branchname..origin/branchname

        # 查看兩個 commit 的對比
        $ git diff commit1..commit2

        remote

        # 查看所有遠程主機
        $ git remote
        # 查看關(guān)聯(lián)的遠程倉庫的詳細信息
        $ git remote -v
        # 刪除遠程倉庫的 “關(guān)聯(lián)”
        $ git remote rm projectname
        # 設(shè)置遠程倉庫的 “關(guān)聯(lián)”
        $ git remote set-url origin

        tag

        常用于發(fā)布版本

        www.liaoxuefeng.com/wiki/896043…

        # 默認在 HEAD 上創(chuàng)建一個標簽
        $ git tag v1.0
        # 指定一個 commit id 創(chuàng)建一個標簽
        $ git tag v0.9 f52c633
        # 創(chuàng)建帶有說明的標簽,用 -a 指定標簽名,-m 指定說明文字
        $ git tag -a v0.1 -m "version 0.1 released"

        # 查看所有標簽
        # 注意:標簽不是按時間順序列出,而是按字母排序的。
        $ git tag

        # 查看單個標簽具體信息
        $ git show

        # 推送一個本地標簽
        $ git push origin
        # 推送全部未推送過的本地標簽
        $ git push origin --tags

        # 刪除本地標簽
        # 因為創(chuàng)建的標簽都只存儲在本地,不會自動推送到遠程。
        # 所以,打錯的標簽可以在本地安全刪除。
        $ git tag -d v0.1
        # 刪除一個遠程標簽(先刪除本地 tag ,然后再刪除遠程 tag)
        $ git push origin :refs/tags/

        刪除文件

        # 刪除暫存區(qū)和工作區(qū)的文件
        $ git rm filename
        # 只刪除暫存區(qū)的文件,不會刪除工作區(qū)的文件
        $ git rm --cached filename

        如果在配置 .gitignore 文件之前就把某個文件上傳到遠程倉庫了,這時候想把遠程倉庫中的該文件刪除,此時你配置 .gitignore 文件也沒有用,因為該文件已經(jīng)被追蹤了,但又不想在本地刪除該文件后再重新提交到遠程倉庫,這時候可以使用 git rm --cached filename 命令取消該文件的追蹤,這樣下次提交的時候,git 就不會再提交這個文件,從而遠程倉庫的該文件也會被刪除

        版本切換 & 重設(shè) & 撤銷

        • 「checkout 可以撤銷工作區(qū)的文件,reset 可以撤銷工作區(qū)/暫存區(qū)的文件」
        • 「reset 和 checkout 可以作用于 commit 或者文件,revert 只能作用于 commit」

        checkout 詳解

        # 恢復暫存區(qū)的指定文件到工作區(qū)
        $ git checkout
        # 恢復暫存區(qū)的所有文件到工作區(qū)
        $ git checkout .

        # 回滾到最近的一次提交
        # 如果修改某些文件后,沒有提交到暫存區(qū),此時的回滾是回滾到上一次提交
        # 如果是已經(jīng)將修改的文件提交到倉庫了,這時再用這個命令回滾無效
        # 因為回滾到的是之前自己修改后提交的版本
        $ git checkout HEAD
        $ git checkout HEAD -- filename
        # 回滾到最近一次提交的上一個版本
        $ git checkout HEAD^
        # 回滾到最近一次提交的上2個版本
        $ git checkout HEAD^^

        # 切換分支,在這里也可以看做是回到項目「當前」狀態(tài)的方式
        $ git checkout <當前你正在使用的分支>
        # 切換到某個指定的 commit 版本
        $ git checkout
        # 切換指定 tag
        $ git checkout

        • 「在開發(fā)的正常階段,HEAD 一般指向 master 或是其他的本地分支,但當你使用 git checkout 切換到指定的某一次提交的時候,HEAD 就不再指向一個分支了——它直接指向一個提交,HEAD 就會處于 detached 狀態(tài)(游離狀態(tài))」。
        • 切換到某一次提交后,你可以查看文件,編譯項目,運行測試,甚至編輯文件而不需要考慮是否會影響項目的當前狀態(tài),你所做的一切都不會被保存到主棧的倉庫中。當你想要回到主線繼續(xù)開發(fā)時,使用 git checkout branchName 回到項目初始的狀態(tài)(「這時候會提示你是否需要新建一條分支用于保留剛才的修改」)。
        • 「哪怕你切換到了某一版本的提交,并且對它做了修改后,不小心提交到了暫存區(qū),只要你切換回分支的時候,依然會回到項目的初始狀態(tài)。(***注意:你所做的修改,如果 commit 了,會被保存到那個版本中。切換完分支后,會提示你是否要新建一個分支來保存剛才修改的內(nèi)容。如果你剛才解決了一個 bug ,這時候可以新建一個臨時分支,然后你本地自己的開發(fā)主分支去合并它,合并完后刪除臨時分支***)?!?/strong>
        • 「一般我都是用 checkout 回退版本,查看歷史代碼,測試 bug 在哪」

        reset 詳解

        git reset [--hard|soft|mixed|merge|keep] [或HEAD]:將當前的分支重設(shè)(reset)到指定的 或者 HEAD (默認,如果不顯示指定 ,默認是 HEAD ,即最新的一次提交),并且根據(jù) [mode] 有可能更新索引和工作目錄。mode 的取值可以是 hardsoft、mixed、merged、keep

        # 從暫存區(qū)撤銷特定文件,但不改變工作區(qū)。它會取消這個文件的暫存,而不覆蓋任何更改
        $ git reset
        # 重置暫存區(qū)最近的一次提交,但工作區(qū)的文件不變
        $ git reset
        # 等價于
        $ git reset HEAD (默認)
        # 重置暫存區(qū)與工作區(qū),回退到最近一次提交的版本內(nèi)容
        $ git reset --hard
        # 重置暫存區(qū)與工作區(qū),回退到最近一次提交的上一個版本
        $ git reset --hard HEAD^

        # 將當前分支的指針指向為指定 commit(該提交之后的提交都會被移除),同時重置暫存區(qū),但工作區(qū)不變
        $ git reset
        # 等價于
        $ git reset --mixed

        # 將當前分支的指針指向為指定 commit(該提交之后的提交都會被移除),但保持暫存區(qū)和工作區(qū)不變
        $ git reset --soft
        # 將當前分支的指針指向為指定 commit(該提交之后的提交都會被移除),同時重置暫存區(qū)、工作區(qū)
        $ git reset --hard

        • git reset 有很多種用法。它可以被用來移除提交快照,盡管它通常被用來撤銷暫存區(qū)和工作區(qū)的修改。不管是哪種情況,它應該只被用于本地修改——你永遠不應該重設(shè)和其他開發(fā)者共享的快照。
        • 「當你用 reset 回滾到了某個版本后,那么在下一次 git 提交時,之前該版本后面的版本會被作為垃圾刪掉。」
        • 「當我們回退到一個舊版本后,此時再用 git log 查看提交記錄,會發(fā)現(xiàn)之前的新版本記錄沒有了。如果第二天,你又想恢復到新版本怎么辦?找不到新版本的 commit_id 怎么辦?」

        「我們可以用 git reflog 查看歷史命令,這樣就可以看到之前新版本的 commit_id ,然后 git reset --hard commit_id 就可以回到之前的新版本代碼」

        • 雖然可以用 git reflog 查看本地歷史,然后回復到之前的新版本代碼,但是在別的電腦上是無法獲取你的歷史命令的,所以這種方法不安全。萬一你的電腦突然壞了,這時候就無法回到未來的版本。

        revert 詳解

        # 生成一個撤銷最近的一次提交的新提交
        $ git revert HEAD
        # 生成一個撤銷最近一次提交的上一次提交的新提交
        $ git revert HEAD^
        # 生成一個撤銷最近一次提交的上兩次提交的新提交
        $ git revert HEAD^^
        # 生成一個撤銷最近一次提交的上n次提交的新提交
        $ git revert HEAD~num

        # 生成一個撤銷指定提交版本的新提交
        $ git revert
        # 生成一個撤銷指定提交版本的新提交,執(zhí)行時不打開默認編輯器,直接使用 Git 自動生成的提交信息
        $ git revert --no-edit

        git revert命令用來「撤銷某個已經(jīng)提交的快照(和 reset 重置到某個指定版本不一樣)」。它是在提交記錄最后面加上一個撤銷了更改的新提交,而不是從項目歷史中移除這個提交,這避免了 Git 丟失項目歷史。

        「撤銷(revert)應該用在你想要在項目歷史中移除某個提交的時候」。比如說,你在追蹤一個 bug,然后你發(fā)現(xiàn)它是由一個提交造成的,這時候撤銷就很有用。

        「撤銷(revert)被設(shè)計為撤銷公共提交的安全方式,重設(shè)(reset)被設(shè)計為重設(shè)本地更改?!?/strong>

        因為兩個命令的目的不同,它們的實現(xiàn)也不一樣:重設(shè)完全地移除了一堆更改,而撤銷保留了原來的更改,用一個新的提交來實現(xiàn)撤銷。「千萬不要用 git reset 回退已經(jīng)被推送到公共倉庫上的 提交,它只適用于回退本地修改(從未提交到公共倉庫中)。如果你需要修復一個公共提交,最好使用 git revert」。

        發(fā)布一個提交之后,你必須假設(shè)其他開發(fā)者會依賴于它。移除一個其他團隊成員在上面繼續(xù)開發(fā)的提交在協(xié)作時會引發(fā)嚴重的問題。當他們試著和你的倉庫同步時,他們會發(fā)現(xiàn)項目歷史的一部分突然消失了。一旦你在重設(shè)之后又增加了新的提交,Git 會認為你的本地歷史已經(jīng)和 origin/master 分叉了,同步你的倉庫時的合并提交(merge commit)會使你的同事困惑。

        cherry-pick

        「將指定的提交 commit 應用于當前分支」(可以用于恢復不小心撤銷(revert/reset)的提交)

        $ git cherry-pick 
        $ git cherry-pick
        $ git cherry-pick ^..

        git submodule 子模塊

        有種情況我們經(jīng)常會遇到:某個工作中的項目需要包含并使用另一個項目。也許是第三方庫,或者你獨立開發(fā)的,用于多個父項目的庫。現(xiàn)在問題來了:你想要把它們當做兩個獨立的項目,同時又想在一個項目中使用另一個。如果將另外一個項目中的代碼復制到自己的項目中,那么你做的任何自定義修改都會使合并上游的改動變得困難。「Git 通過子模塊來解決這個問題,允許你將一個 Git 倉庫作為另一個 Git 倉庫的子目錄。它能讓你將另一個倉庫克隆到自己的項目中,同時還保持提交的獨立?!?/strong>

        # 在主項目中添加子項目,URL 為子模塊的路徑,path 為該子模塊存儲的目錄路徑
        git submodule add [URL] [Path]

        # 克隆含有子項目的主項目
        git clone [URL]
        # 當你在克隆這樣的項目時,默認會包含該子項目的目錄,但該目錄中還沒有任何文件
        # 初始化本地配置文件
        git submodule init
        # 從當前項目中抓取所有數(shù)據(jù)并檢出父項目中列出的合適的提交
        git submodule update
        # 等價于 git submodule init && git submodule update
        git submodule update --init

        # 自動初始化并更新倉庫中的每一個子模塊, 包括可能存在的嵌套子模塊
        git clone --recurse-submodules [URL]

        新建一個 Git 項目的兩種方式

        1.本地新建好 Git 項目,然后關(guān)聯(lián)遠程倉庫

        # 初始化一個Git倉庫
        $ git init
        # 關(guān)聯(lián)遠程倉庫
        $ git remote add
        # 例如
        $ git remote add origin https://github.com/xxxxxx

        2.clone 遠程倉庫

        # 新建好遠程倉庫,然后 clone 到本地
        $ git clone

        # 將遠程倉庫下載到(當前 git bash 啟動位置下面的)指定文件中,如果沒有會自動生成
        $ git clone

        Git 分支管理規(guī)范

        blog.csdn.net/LitongZero/…

        juejin.im/post/5b4328…

        • 實際開發(fā)的時候,一人一條分支(

          個人見解:除非是大項目,參與的開發(fā)人員很多時,可以采用 feature 分支,否則一般的項目中,一個開發(fā)者一條分支夠用了

          )。除此之外還要有一條 develop 開發(fā)分支,一條 test 測試分支,一條 release 預發(fā)布分支。

          • 「develop」「開發(fā)分支」,開發(fā)人員每天都需要拉取/提交最新代碼的分支;
          • 「test」「測試分支」,開發(fā)人員開發(fā)完并自測通過后,發(fā)布到測試環(huán)境的分支;
          • 「release」「預發(fā)布分支」,測試環(huán)境測試通過后,將測試分支的代碼發(fā)布到預發(fā)環(huán)境的分支(「這個得看公司支不支持預發(fā)環(huán)境,沒有的話就可以不采用這條分支」);
          • 「master」「線上分支」,預發(fā)環(huán)境測試通過后,運營/測試會將此分支代碼發(fā)布到線上環(huán)境;
        • 大致流程:

          • 開發(fā)人員每天都需要拉取/提交最新的代碼到 「develop 分支」
          • 開發(fā)人員開發(fā)完畢,開始 「集成測試」,測試無誤后提交到 「test 分支」并發(fā)布到測試環(huán)境,交由測試人員測試;
          • 測試環(huán)境通過后,發(fā)布到 「release 分支」 上,進行預發(fā)環(huán)境測試;
          • 預發(fā)環(huán)境通過后,發(fā)布到 「master 分支」上并打上標簽(tag);
          • 如果線上分支出了 bug ,這時候相關(guān)開發(fā)者應該基于預發(fā)布分支(「沒有預發(fā)環(huán)境,就使用 master 分支」),新建一個 「bug 分支」用來臨時解決 bug ,處理完后申請合并到 預發(fā)布 分支。這樣做的好處就是:不會影響正在開發(fā)中的功能。

        「預發(fā)布環(huán)境的作用:」 預發(fā)布環(huán)境是正式發(fā)布前最后一次測試。因為在少數(shù)情況下即使預發(fā)布通過了,都不能保證正式生產(chǎn)環(huán)境可以100%不出問題;預發(fā)布環(huán)境的配置,數(shù)據(jù)庫等都是跟線上一樣;有些公司的預發(fā)布環(huán)境數(shù)據(jù)庫是連接線上環(huán)境,有些公司預發(fā)布環(huán)境是單獨的數(shù)據(jù)庫;如果不設(shè)預發(fā)布環(huán)境,如果開發(fā)合并代碼有問題,會直接將問題發(fā)布到線上,增加維護的成本。

        Git 鉤子

        • Git 基本已經(jīng)成為項目開發(fā)中默認的版本管理軟件,在使用 Git 的項目中,我們可以為項目設(shè)置 Git Hooks 來幫我們在提交代碼的各個階段做一些代碼檢查等工作

        • 鉤子(Hooks) 都被存儲在 Git 目錄下的 hooks 子目錄中。也就是絕大部分項目中的 .git/hook 目錄

        • 鉤子

          分為兩大類,客戶端的和服務(wù)器端的

          • 客戶端鉤子主要被提交和合并這樣的操作所調(diào)用
          • 而服務(wù)器端鉤子作用于接收被推送的提交這樣的聯(lián)網(wǎng)操作,這里主要介紹客戶端鉤子

        4.1 pre-commit

        • pre-commit 就是在代碼提交之前做些東西,比如代碼打包,代碼檢測,稱之為鉤子(hook)
        • 在 commit 之前執(zhí)行一個函數(shù)(callback)。這個函數(shù)成功執(zhí)行完之后,再繼續(xù) commit,但是失敗之后就阻止 commit
        • 在 .git->hooks->下面有個 pre-commit.sample* ,這個里面就是默認的函數(shù)(腳本)樣本

        4.2 安裝 pre-commit

        npm install pre-commit --save-dev

        4.3 配置腳本

        「如果沒有在 .git->hooks 目錄下生成 pre-commit 文件的話,則要手工創(chuàng)建 node ./node_modules/pre-commit/install.js

        "scripts": {
        "build": "tsc",
        "eslint": "eslint src --ext .ts",
        "eslint:fix": "eslint src --ext .ts --fix"
        },
        //在提交代碼之前,先執(zhí)行 scripts 中的 eslint 命令
        "pre-commit": [
        "eslint"
        ]

        4.4 跳過 pre-commit 繼續(xù)提交代碼

        # 跳過驗證
        $ git commit --no-verify
        $ git commit -n

        更多鉤子:git-scm.com/book/zh/v2/…

        常見問題

        1、拉取別人的遠程分支合并后,git 會存取這個拉取的記錄,如果你不小心刪了別人的上傳的文件,這時候想要再拉取別人的分支是沒用的,會顯示 already-up

        這時候可以回滾代碼,重新拉取。

        2、以前有過這樣的經(jīng)歷:前后端、客戶端的代碼都存放在一個 git 倉庫中,在根目錄下各自新建項目目錄。那么可以直接在自己的項目目錄下使用 git 提交代碼并且在各自的項目目錄下配置 .gitignore 文件,不用在根目錄下配置 .gitignore 文件,這樣就互不影響了

        3、fatal:refusing to merge unrelated histories 拒絕合并不相關(guān)的歷史

        在 git 2.9.2 之后,不可以合并沒有相同結(jié)點的分支(分支之間自倉庫建立后,從來沒有過互相拉取合并)。如果需要合并兩個不同結(jié)點的分支,如下:

        $ git pull origin branchName --allow-unrelated-histories
        $ git merge branchName --allow-unrelated-histories

        這個功能是可以讓大家不要把倉庫上傳錯了,如果會加上這個代碼,那么就是自己確定了上傳。舊版本的 Git 很容易就把代碼傳錯了,現(xiàn)在可以看到,如果上傳的不是之前的,那么就需要加代碼上傳。正常情況下,都是先建立倉庫,然后切多個分支,分支先去拉取合并主分支的內(nèi)容,然后再各自開發(fā), 如果建立倉庫后,各個分支沒有區(qū)拉取主分支的代碼,之后各個分支之間想要合并時就會報錯。

        4、合并分支時出現(xiàn)問題,想要解除合并狀態(tài)

        error: merge is not possible because you have unmerged files.
        hint: Fix them up in the work tree, and then use 'git add/rm '
        hint: as appropriate to mark resolution and make a commit.
        fatal: Exiting because of an unresolved conflict.

        當遠程分支和本地分支發(fā)生沖突后,git 保持合并狀態(tài),你如果沒有去解決完所有的沖突,那么 git 會一直保持這個狀態(tài),你就無法再提交代碼。只有先解除合并狀態(tài)后,才能繼續(xù)提交。執(zhí)行命令前最好先備份一下,有可能本地做的修改會被遠程分支覆蓋掉。

        # 解除合并狀態(tài)
        $ git merge --abort

        5、不小心把某些文件上傳到遠程 git 倉庫/想要刪除遠程倉庫中的文件

        # 刪除暫存區(qū)和工作區(qū)的文件
        $ git rm filename
        # 只刪除暫存區(qū)的文件,不會刪除工作區(qū)的文件
        $ git rm --cached filename

        如果在配置 .gitignore 文件之前就把某個文件上傳到遠程倉庫了,這時候想把遠程倉庫中的該文件刪除,此時你配置 .gitignore 文件也沒有用,因為該文件已經(jīng)被追蹤了,但又不想在本地刪除該文件后再重新提交到遠程倉庫,這時候可以使用 git rm --cached filename 命令取消該文件的追蹤,這樣下次提交的時候,git 就不會再提交這個文件,從而遠程倉庫的該文件也會被刪除

        6、將本地新建的項目上傳到新建的遠程倉庫上

        之前沒有進行過關(guān)聯(lián),即沒有通過 clone 遠程項目到本地再開始做項目,而是先本地新建了一個項目,然后想傳到遠程倉庫上。

        # 將本地倉庫和遠程倉庫關(guān)聯(lián)起來
        $ git remote add origin 遠程倉庫地址
        # 將本地的 master 分支推送到 origin 主機,同時指定 origin 為默認主機
        $ git push -u origin master
        # 上面的命名執(zhí)行后,下次再從本地庫上傳內(nèi)容的時候只需下面這樣就可以了
        $ git push

        7、HEAD 指針既可以指向分支(默認指向當前分支),也可以指向快照,當指向的是快照時,這個時候指針的狀態(tài)稱之為游離狀態(tài)(detached)

        8、創(chuàng)建與合并分支的原理

        www.liaoxuefeng.com/wiki/896043…

        9、每次 git push 都要輸入用戶名、密碼

        • step 1:生成公鑰
        ssh-keygen -t rsa -C "[email protected]"
        # Generating public/private rsa key pair...
        # 三次回車即可生成 ssh key
        • step 2:查看已生成的公鑰
        cat ~/.ssh/id_rsa.pub
        • step3:復制已生成的公鑰添加到 git 服務(wù)器

        測試 ssh 是否能夠連接成功

        $ ssh -T [email protected]

        • step4:使用 ssh 協(xié)議 clone 遠程倉庫 或者 如果已經(jīng)用 https 協(xié)議 clone 到本地了,那么就重新設(shè)置遠程倉庫

        「使用 ssh 協(xié)議」

        $ git remote set-url origin [email protected]:xxx/xxx.git
        • step5:創(chuàng)建文件存儲用戶名和密碼

        一般為 C:\users\Administrator,也可以是你自己創(chuàng)建的系統(tǒng)用戶名目錄,文件名為 .git-credentials。由于在 Windows 中不允許直接創(chuàng)建以 "." 開頭的文件,所以用命令行創(chuàng)建該文件。

        $ touch .git-credentials
        $ echo "http://{username}:{password}@github.com" >> ~/.git-credentials
        $ git config --global credential.helper store

        10、git 不允許提交空文件夾

        可以在當前目錄下,添加一個 .gitkeep 文件

        11、有時候復制過來的文件,使用 git add . 無法進行文件追蹤,可以使用 git add -A ,這也就是每次提交前都要 git status 的原因

        12、同一臺電腦配置多個 git 賬號

        github.com/jawil/notes…

        13、Another git process seems to be running in this repository, e.g.

        原因在于 Git 在使用過程中遭遇了奔潰,部分被上鎖資源沒有被釋放導致的。

        「解決方案:」 進入項目文件夾下的 .git 文件中(顯示隱藏文件夾或 rm .git/index.lock)刪除 index.lock 文件即可。

        14、git commit -am "xxx" 有時候會失效,無法提交所有的修改

        git commit -am "xxx" 只會將被 「tracked」 的文件添加到暫存區(qū)并提交,而將文件添加到 git 管理是要使用 git add 命令,將新的文件 「tracked」 。(新建了文件之后,idea 會提示你是否需要加到 git 管理中。選擇記住后,之后 idea 默認都會把新建的文件 「tracked」 化)

        15、git merge --no-ff 的作用

        • 「禁止快進式(fast-forward)合并,會生成一個新的提交」

        從合并后的代碼來看,結(jié)果都是一樣的,區(qū)別就在于 --no-ff 會讓 git 生成一個新的提交對象。為什么要這樣?通常我們把 master 作為主分支,上面存放的都是比較穩(wěn)定的代碼,提交頻率也很低,而 feature 是用來開發(fā)特性的,上面會存在許多零碎的提交,快進式合并會把 feature 的提交歷史混入到 master 中,攪亂 master 的提交歷史。所以如果你根本不在意提交歷史,也不愛管 master 干不干凈,那么 --no-ff 其實沒什么用。

        segmentfault.com/q/101000000…

        16、git merge 與 git rebase 的區(qū)別

        juejin.im/post/5a5438…

        blog.csdn.net/liuxiaoheng…

        segmentfault.com/a/119000001…

        segmentfault.com/a/119000001…

        17、git log 無法正常顯示中文

        # 試試
        $ git -c core.pager=more log
        # 如果可以顯示中文的話,把 pager 設(shè)置為 more
        $ git config --global core.pager more

        www.zhihu.com/question/57…

        www.playpi.org/2019031901.…

        18、git merge -m "xxx" 的時候可以附加信息

        • 默認是 Merge branch branchName

        19、git pull 會拉取所有遠程分支的代碼到本地鏡像倉庫中

        想要 merge 別人的分支時:

        • 如果你的本地倉庫中已經(jīng)有了他人的分支(直接切換到他人分支,就會在本地生成一條他人的分支),就可以使用 merge branchname;
        • 如果你的本地倉庫沒有他人的分支,那么就得使用 merge origin/branchname 來合并

        20、git branch -r/-a/-l 查看的都是本地鏡像倉庫中的分支,如果本地鏡像倉庫沒有拉取遠程倉庫的代碼,此時別人新推了一個分支到遠程倉庫,你這時候是查看不到這條新推的分支的

        21、git stash 存儲未追蹤的文件

        • 如果我們新建了文件,但是沒有用 git add . 追蹤文件,那么 git stash 是無法存儲的
        $ git stash -u

        22、如何在 github 上 pr 項目

        segmentfault.com/a/119000002…

        23、git push 無法提交代碼

        「可能出現(xiàn)的報錯:」

        • 「remote:」 Permission to xxxxx.git denied to xxx. fatal: unable to access 'github.com/ xxxxx.git/': The requested URL returned error: 403

        • 「remote:」 You do not have permission to push to the repository via HTTPS

          「fatal:」 Authentication failed for 'gitee.com/xxx.git/'

        # 查看當前項目的 git 配置
        $ cat .git/config
        • 查看本地項目的 .git/config 設(shè)置的倉庫 url 地址和 github 使用的鏈接地址是否一致。git push 的數(shù)據(jù)協(xié)議有兩種方式:sshhttps。如果不一致就需要切換 url 地址。

        24、git 輸錯用戶名和密碼,后續(xù)的 git 操作一直報錯

        remote: Coding 提示: Authentication failed.
        remote: 認證失敗,請確認您輸入了正確的賬號密碼。
        fatal: Authentication failed for 'https://e.coding.net/xxx.git/'

        在控制面板里找到憑據(jù)管理器,選中 Windows 憑據(jù),找到 git 的憑據(jù),點擊編輯,輸入所用 github 的正確用戶名和密碼。

        25、lint-staged 失敗

        可能你的項目名路徑中包含了中文名,需要替換成英文名

        26、查看 git 安裝目錄

        • 「Mac:」 在命令行中輸入 which git,就會顯示 git 的安裝位置了
        • 「Windows:」 打開cmd,輸入 where git,就會顯示 git 的安裝路徑了

        27、Git中用vim打開、修改、保存文件

        28、windows10 無法編輯 vimrc

        29、Windows下Git Bash中VIM打開文件中文亂碼

        30、如何修改舊的 commit 的 message/如何將多個 commit 合成一個 commit/如何將多個間隔的 commit 合成一個 commit/

        git rebase -i

        31、如果兩個人都對某個文件進行了修改,一個是重命名文件,一個是修改文件內(nèi)容,那么會起沖突嗎?git 很智能,會自動合并這些修改

        如果兩個人都對同一個文件重命名,此時會起沖突,git 不會自動處理,需要開發(fā)者自身去解決沖突

        32、git revert 失?。篹rror: Commit faulty merge is a merge but no -m option was given、error: option `mainline' expects a number greater than zero

        segmentfault.com/a/119000001…

        www.jianshu.com/p/3719dae37…

        git revert -m 1

        33、git 創(chuàng)建一個空的分支

        在 Git 中創(chuàng)建分支,是必須有一個父節(jié)點的,也就是說必須在已有的分支上來創(chuàng)建新的分支,如果工程已經(jīng)進行了一段時間,這個時候是無法創(chuàng)建空分支的。但是有時候就是需要創(chuàng)建一個空白的分支。

        $ git checkout --orphan emptyBranchName

        該命令會生成一個叫 emptybranch 的分支,該分支會包含父分支的所有文件。但新的分支不會指向任何以前的提交,就是它沒有歷史,如果你提交當前內(nèi)容,那么這次提交就是這個分支的首次提交。

        想要空分支,所以需要把當前內(nèi)容全部刪除,用 git 命令

        $ git rm -rf . // 注意:最后的‘.’不能少。

        34、如何清空一個分支的所有提交

        先刪除該分支,然后再新建一個空的分支(分支名就是刪除的分支名)~~

        推薦閱讀:

        實戰(zhàn):一鍵生成前后端代碼,Mybatis-Plus代碼生成器讓我舒服了
        為什么要重寫 hashcode 和 equals 方法?
        SpringBoot @Value 解析集合配置

        瀏覽 44
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            北条麻妃中文字幕旡码| 热九九精品| 先锋影音麻豆| 国产性爱网站| 一级a一级a免费观看免免黄‘/| 各种妇女撒尿mm毛免费网站 | 久久久无码电影| 日韩无码字幕| 国产九色91回来了| 一道本无码视频|