工具- git 低頻命令

語言: CN / TW / HK

theme: smartblue

開啟掘金成長之旅!這是我參與「掘金日新計劃 · 12 月更文挑戰」的第1天,點選檢視活動詳情

前言

雖然現在git都用可視化了,但是我還是比較喜歡結合命令列去做一些事情,尤其是在批量操作的倉庫的時候。
恰好最近接觸到了一個大型專案,需要頻繁的同步各個版本的倉庫,並在這上面浪費了很多的時間,有一些場景還是值得記錄一下的。

正常流程

```shell

最基本

1- 新建倉庫/分支 2- git clone 3- git add . 4- git commit -m 'aaa' 5- git push

本地開始

1- git init 2- git remote add origin "http://gitee..." 3- git push

開發特性功能

1- git clone 2- git checkout -b feature/造火箭 3- git add . 4- git commit -m '做推進器1' 5- git add . 6- git commit -m '做推進器2' 7- git add . 8- git commit -m '做推進器3' 9- git checkout master 10- git pull 11- git merge feature/造火箭 12- git push

```

小細節(多遠端倉庫)

  1. git push "遠端地址別名" "分支名(可加可不加)"
  2. git pull "遠端地址別名" "分支名(可加可不加)"
  3. git remote add "遠端地址別名" "倉庫地址"
  4. git merge --strategy-option=ours/theirs B
  5. git add fileA fileB
  6. git checkout -- [fileA fileB]/ .

幾個稍微特殊的場景

場景一

前置條件:倉庫 A(有上千個 commit 記錄),空倉庫 B。 需求:基於倉庫 A branch v1.0 commitID asd12345 建立新的分支 v1.0-feature 提交到 倉庫 B,並保留 commit 記錄。

場景二

前置條件:倉庫 A(很複雜),倉庫 B是由 倉庫A 通過場景一分離出去的,已經有了新的 commit tree。 需求:將倉庫 A 中的 連續/不連續 的commit 合併進 倉庫 B 的 v1.0-feature 分支,不打亂原有的 commit 記錄。

場景三

前置條件:倉庫 A(很複雜),主分支 master、特性分支 feature1、開發分支 dev1,feature1 早於 dev1 且有衝突。 需求:完整的提取 feature ,並 不影響現在的dev環境。

場景四

正常開發 add commit push,因為 commit 不夠美觀,最新一個 commit 不想要了。

場景五

一個 demo 庫性質的倉庫,即你下載了別人的一個倉庫,倉庫的提交記錄特別整齊,每個 commit 都是一個完整的 demo,你想要把 某個 demo 放在你的專案裡面,即 cherrypick 一個跟你的倉庫完全沒關係的 commitID。

場景六

一個倉庫兩個團隊都在更新內容,如何確保程式碼合併時候,雙方都不會受到影響?

場景七

三個分支,一個是持續迭代分支,一個是主分支,還有一個或多個是新需求分支,合併需求的時候,發現需求分支上舊版本把另一個迭代版本覆蓋了。

場景八

一個需求經過開發、聯調、上線、解決bug一系列操作才完成,希望能把這一系列的 commitID 合併成 一條記錄。

場景九

配置一個本地倉庫,可以向客戶A、客戶B、公司倉庫推送程式碼。

一個綜合性比較強的場景

sh echo -e "\033[36m :: Start 克隆遠端倉庫 -fe-watermark-- \033[0m" && git clone http://gitee.com/RELEASE/watermark.git && echo -e "\033[36m :: 進入倉庫 fe-watermark --- \033[0m" && cd fe-watermark && echo -e "\033[36m :: 新增新遠端地址 \033[0m" && git remote add kt http://github.com/project/watermark.git && git remote -v && echo -e "\033[36m :: 切換至目標分支 --- \033[0m" && git checkout di/dev-v1.2.0 && echo -e "\033[36m :: 推送 dev_1.0.0--- \033[0m" && git checkout -b dev_1.0.0 && git push kt dev_1.0.0 -f && echo -e "\033[36m :: 拉取 master--- \033[0m" && git pull kt master && git checkout master && echo -e "\033[36m :: 比對 master | di/dev-v1.2.0--- \033[0m" && git diff di/dev-v1.2.0 master && echo -e "\033[36m :: 重置 master--- \033[0m" && git reset --hard dev_1.0.0 && echo -e "\033[36m :: 再次比對 master | di/dev-v1.2.0--- \033[0m" && git diff di/dev-v1.2.0 master && echo -e "\033[36m :: 推送 master--- \033[0m" && git push kt master -f && echo -e "\033[36m :: 完成 - Exit -- \033[0m" && cd ..

具體場景是這樣的,有一個大型專案,倉庫30+,需要對所有的倉庫都新建一個倉庫並且將現有倉庫的指定分支重新命名推送到新的倉庫,並且master要和這個重新命名的分支同步。

舉個現實場景就是,我們公司開發的程式碼,基於 dev-1.2 改成 xxx-1.0 並新建倉庫交付給客戶,然後加個小條件就是把現在的程式碼放在master分支上。很不巧的是,昨天剛做了一趟,現在而且程式碼管理員很貼心的給了另一套倉庫地址,裡面的分支更加清晰。

就是說,我昨天從 A 列表中 將 a 分支 改名 為 a1 同步到了 B 列表,現在 又要把 C 列表當做 A 列表再來一次。關鍵點是不同源了。B列表又不能新建一遍。

好像工作並不難,難的是如何保證不出錯,高效的完成這件事情,即便出錯了也能很快的追溯當時發生了什麼,迅速的進行解決。

如上命令呼叫所示,直接實現了這個情況。核心有兩個: - push -f - reset --hard

還有一些 remote 相關的操作。

之所以寫成這麼一坨的原因是因為避免出錯,需要修改的只有三個地方,clone 地址,remote 地址,舊分支名稱。那麼是不是可以這麼理解: - 如果前端寫一個表單,就可以通過輸入這三個內容太就可以完成者一系列操作了? - 更高階一點,這些資訊原來放在 excel 裡面,我也可以通過解析 excel 的方式拿到這三個資訊,實現完全自動化?當然這個需要藉助一點 node 的知識,但是不多。

這種純體力勞動,越少手動操作越少犯錯,而且倉庫越多越能體現優勢。

合併不同來源的分支

$ git merge master --allow-unrelated-histories

拉去遠端覆蓋本地

shell $ git reset --hard origin/master $ git pull origin master

修改遠端倉庫地址

shell git remote set-url [--push] <name> <newurl> [<oldurl>] git remote set-url --add [--push] <name> <newurl> git remote set-url --delete [--push] <name> <url>

配置一個倉庫對應多個遠端倉庫

如下,git裡面的 config 檔案長這樣:

```shell

.git/config

[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true symlinks = false ignorecase = true hooksPath = .husky [remote "origin"] url = http://gitee.com/jci/datasource.git fetch = +refs/heads/:refs/remotes/origin/ [remote "nlc"] url = http://github.com/DI-WEB/dataSource.git fetch = +refs/heads/:refs/remotes/origin/ [branch "master"] remote = origin merge = refs/heads/master [branch "di/v_1.2"] remote = origin merge = refs/heads/di/v_1.2 [branch "di/dev-v1.2.2"] remote = nlc merge = refs/heads/di/dev-v1.2.2 ```