# git 實作練習 5 @ver 0.1.1 @date 2019-04-19 21:37:21 (星期五) > 上一篇實作遠端倉庫, 衝突合併後, 不同的開發者出現寫入權限問題 > > 這一篇我們重頭再來, 但透過 ssh 使用一個共用的帳號, 就叫它 `g` , **注意** 帳號就一個字 `g` , git 的第一個英文字, 可以少打幾個字 **注意** 以下的文章, 若有 `#### **@G**` 標記, 表示不同於上一篇的差異說明, 請仔細閱讀 [來源 : 伺服器上的 Git - 架設伺服器](https://git-scm.com/book/zh-tw/v1/伺服器上的-Git-架設伺服器) 999. ## 開發者 : 金鑰 ### 每位開發者請使用 ssh-keygen 各自建立 #### 命令 ```bash cd ~ mkdir .ssh chmod 700 .ssh cd .ssh ls -la ssh-keygen -t rsa # 一直按 ENTER 直到結束 ls -la # 可以看到 `公開金鑰 id_rsa.pub` 及 `私密金鑰 id_rsa` 兩個檔案 # 以下文章簡稱 `公鑰` 及 `私鑰` ``` #### 執行結果 ```shell [alex2@nvda ~ ]$ cd ~ [alex2@nvda ~ ]$ mkdir .ssh [alex2@nvda ~ ]$ chmod 700 .ssh [alex2@nvda ~ ]$ cd .ssh [alex2@nvda ~/.ssh ]$ ls -la 總計 8 drwx------ 2 alex2 admin 4096 4月 13 08:04 . drwxr-xr-x 9 alex2 admin 4096 4月 19 13:29 .. [alex2@nvda ~/.ssh ]$ [alex2@nvda ~/.ssh ]$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/alex2/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/alex2/.ssh/id_rsa. Your public key has been saved in /home/alex2/.ssh/id_rsa.pub. The key fingerprint is: SHA256:8QjjdgpuJBgbfYEPZpeSofmM16BDy59eyVdop643LTg alex2@nvda.org.tw The key's randomart image is: +---[RSA 2048]----+ | .+.. | | +B o. | |=+o=. o . | |oX.+.. o.+ | |*o= + ooSo. | | o.+oooo+ | | oo+oo. | | ...Eo+ . | | . .+.o | +----[SHA256]-----+ [alex2@nvda ~/.ssh ]$ [alex2@nvda ~/.ssh ]$ ls -la 總計 16 drwx------ 2 alex2 admin 4096 4月 19 22:10 . drwxr-xr-x 9 alex2 admin 4096 4月 19 13:29 .. -rw------- 1 alex2 admin 1675 4月 19 22:10 id_rsa -rw-r--r-- 1 alex2 admin 399 4月 19 22:10 id_rsa.pub [alex2@nvda ~/.ssh ]$ ``` 複製一份自己的 `公鑰` 到 `/tmp/` 目錄下, 但每個人要先改名, 避免檔名重複. 稍後給共用帳號 `g` 加入到它的 `authorized_keys` 讓 git 認證用, 完成後即可刪除 例如 : `cp ~/.ssh/id_rsa.pub /tmp/id_rsa.alex.pub` 999. ## 新增本機 git 共用的帳號 `g` ### 新增帳號 g #### 命令 ```bash sudo -i adduser g su g cd mkdir .ssh ls -la .ssh ``` #### 執行結果 ```shell [alex@nvda ~ ]$ sudo -i [sudo] password for alex: root@nvda:~# adduser g ...(略) Is the information correct? [Y/n] root@nvda:~# root@nvda:~# su g g@nvda:/root$ cd g@nvda:~$ mkdir .ssh g@nvda:~$ g@nvda:~$ ls -la .ssh 總計 8 drwxr-xr-x 2 g g 4096 4月 19 22:02 . drwxr-xr-x 3 g g 4096 4月 19 22:02 .. g@nvda:~$ ``` ### 所有開發者的公鑰 我先把我兩個帳號的公鑰加入 `~/.ssh/authorized_keys` , 其他開發請自行想辦法操作加入 :-) #### 命令 ```bash ls -l /tmp/*.pub cat /tmp/id_rsa.alex.pub >> ~/.ssh/authorized_keys cat /tmp/id_rsa.alex2.pub >> ~/.ssh/authorized_keys ...其他開發請自行想辦法操作加入 :-D ``` #### 執行結果 ```shell g@nvda:~$ ls -l /tmp/*.pub -rw-r--r-- 1 alex2 admin 399 4月 19 22:20 /tmp/id_rsa.alex2.pub -rw-r--r-- 1 alex admin 398 4月 19 22:20 /tmp/id_rsa.alex.pub g@nvda:~$ cat /tmp/id_rsa.alex.pub >> ~/.ssh/authorized_keys g@nvda:~$ cat /tmp/id_rsa.alex2.pub >> ~/.ssh/authorized_keys g@nvda:~$ ls -l ~/.ssh/authorized_keys -rw-r--r-- 1 g g 797 4月 19 22:25 /home/g/.ssh/authorized_keys g@nvda:~$ ``` ### **重要** 不淮 `g` 登入 shell 請在完成 `g` 的遠端倉庫並初始化後再設定. git 有一個額外的防範措施, 它內建 git-shell 工具限制此帳號的活動範圍. 只要把 `/usr/bin/git-shell` 用戶就無法使用普通的 bash 或者 csh 的 shell 程式. #### 命令 ```bash sudo vipw ``` #### 執行結果 ```shell g:x:1002:1001:,,,:/home/g:/bin/bash # 改為 g:x:1002:1001:,,,:/home/g:/usr/bin/git-shell ``` 999. ## 建立者 : 遠端倉庫 ### 建立本機的建立遠端倉庫並初始化 **重要** 只要執行一次. 我們把遠端倉庫放在 `/home/g/repo` 目錄名稱不重要, 用新的使用者 `g` 建立, 並設定共同開發者群組權限. #### 命令 ```bash sudo -i #### **@G** 切換為帳號 g su g #### **@G** 回到 g 的家 cd /home/g mkdir repo cd repo git init --bare ls -la cd .. #### **@G** 權限, `o-rwx` , 好像 `g-rwx` 也可以設, 因為所有共同開發者都只會用到 `user g` chmod -fR o-rwx repo/ tree -f repo/ du -csb repo/ ``` #### 執行結果及說明 ```shell # 更換為 root 身份 [alex@nvda ~ ]$ sudo -i # **注意** 切換為帳號 g root@nvda:~# su g # **注意** 回到 g 的家 g@nvda:/root$ cd /home/g # 建立遠端倉庫子目錄, 名為 `repo` g@nvda:~$ mkdir repo # 進入子目錄 g@nvda:~$ cd repo # 遠端倉庫初始化 g@nvda:~/repo$ git init --bare Initialized empty Git repository in /home/g/repo/ # 查看 g@nvda:~/repo$ ls -la 總計 40 drwxr-xr-x 7 g g 4096 4月 19 22:57 . drwxr-xr-x 4 g g 4096 4月 19 22:57 .. drwxr-xr-x 2 g g 4096 4月 19 22:57 branches -rw-r--r-- 1 g g 66 4月 19 22:57 config -rw-r--r-- 1 g g 73 4月 19 22:57 description -rw-r--r-- 1 g g 23 4月 19 22:57 HEAD drwxr-xr-x 2 g g 4096 4月 19 22:57 hooks drwxr-xr-x 2 g g 4096 4月 19 22:57 info drwxr-xr-x 4 g g 4096 4月 19 22:57 objects drwxr-xr-x 4 g g 4096 4月 19 22:57 refs g@nvda:~/repo$ # 統計 repo 有 9 個目錄, 14 個檔案 g@nvda:~/repo$ cd .. g@nvda:~/repo$ tree -f repo/ ...(略) 9 directories, 14 files # 統計總 Bytes 為 56630 g@nvda:~/repo$ du -cshb repo/ 56630 repo/ 56630 總計 g@nvda:~/repo$ ``` ### 共同開發者們, 權限可讀寫 **重要** : 因為以後所有 `git push pull` 的帳號都會是 `g` 所以不用處理權限可讀寫的問題. 999. ## 建立者 : laravel 基礎框架 ### 基礎框架 **重要** 也是只要執行一次 回到建立者的身份及家目錄, 現在是 `alex`, 我們從頭開始建立一個新的 laravel 專案, 暫時先叫做 `prj0`, 名稱不重要, 這只會當作基礎起點框架上傳到遠端倉庫. 後續此所有共同開發者, 都將會在每個人各自家目錄 clone 回來的專案目錄裡修改操作. ### 建立全新 laravel 專案 建立遠端倉庫用的 laravel 基礎框架時, 先不處理資料庫設定, 但之後各自要把它完成. 每位開發者可以有各自開發用資料庫, 公用測試版也有它的資料庫. 當然, 網站正式上線一定會有正式版專用的資料庫. 同時也不處理 `.env` 及 `vendor 的 composer 安裝`, 這些檔案都被禁止或者不需要上傳至遠端倉庫, 前者是安全問題, 後者是跟隨原開發者會有經常性變動. 詳細可查閱 .gitignore 檔案. #### 命令及說明 ```shell [alex@nvda ~ ]$ laravel new prj0 # 等待約 60 秒 ... 完成 [alex@nvda ~ ]$ cd prj0/ [alex@nvda ~/prj0 ]$ php artisan -V # 版本 Laravel Framework 5.8.12 # 修改系統基礎設定 [alex@nvda ~/prj0 ]$ vi config/app.php # 時間 timezone 預設 UTC, 改為 Asia/Taipei # 本地化 locale 預設 en, 改為 zh-TW # (可不用修改) 另外有一個 'fallback_locale' => 'en', 這個是指如果 'zh-TW' 找不到的話, 它要找誰的語言來替代顯示, 因為所有各種版本都一定有英文對應文字, 所以就用 'en' 即可, 改成 'zh-TW' 或其他語言也沒有什麼問題, 只是可能會顯示空白, 也許剛好可以拿來測試未翻譯本地化的文字. ``` ### git init 及 commit 基礎框架 ```shell git init # Initialized empty Git repository in /home/alex/prj0/.git/ git add . # 本地第一次提交 git commit -m '創立遠端倉庫用的 laravel 基礎框架 5.8.12' git log [alex@nvda ~/prj0 ]$ git log 1 commit 281f0cbb70b2b78e0b65643bc889f6b5adbad636 2 Author: alex 3 Date: Wed Apr 17 07:41:40 2019 +0800 4 5 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex@nvda ~/prj0 ]$ ``` ### **重要** : 設定 git 本地倉庫到遠端倉庫的連結 > **注意** 這一個版本會用到 ssh 連結 > > 如果是從本機以外, 例如我在家裡用 Mac 連回 NVDA 主機, 則改成外部 IP, 但要先完成下列工作, 即可正常使用 #### 命令 ```bash #### **@G** 以下為 g@127.0.0.1 本機內部連結版本 git remote add origin g@127.0.0.1:/home/g/repo #### **@G** 以下為 g@172.104.76.106 從本機以外的連結版本 #### **@G** git remote add origin g@172.104.76.106:/home/g/repo #### **@G** 以下為舊版本, 請比對它們兩個的差異 #### **@G** git remote add origin 127.0.0.1:/home/repo ``` ### git push 遠端倉庫 第一次 `push` 會要求 `The authenticity of host '127.0.0.1 (127.0.0.1)'...` 的授權, 請輸入 `yes` 即可. #### 命令 ```bash git push origin master ``` #### 執行結果 ```shell [alex@nvda ~/prj0 ]$ git push origin master The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established. ECDSA key fingerprint is SHA256:kvXp+0IOtRbKfesB+OxXE2WuNlNeE8WmaY32oZIEfGA. Are you sure you want to continue connecting (yes/no)? Counting objects: 116, done. Delta compression using up to 2 threads. Compressing objects: 100% (98/98), done. Writing objects: 100% (116/116), 236.51 KiB | 0 bytes/s, done. Total 116 (delta 9), reused 0 (delta 0) remote: Resolving deltas: 100% (9/9), done. To 127.0.0.1:/home/g/repo * [new branch] master -> master [alex@nvda ~/prj0 ]$ ``` **完成** 建置 `laravel 基礎框架 5.8.12` 並推送到 `本機內部的遠端倉庫` #### 遠端倉庫第一次 push 之後, 跟先前原始 bare 時統計比對 ```shell # 統計 repo 有 9 個目錄, 17 個檔案 g@nvda:~$ tree -f repo/ ...(略) 9 directories, 17 files # 統計總 Bytes 為 303173 g@nvda:~$ du -csb repo/ 303173 repo/ 303173 總計 g@nvda:~$ ``` #### 番外篇 : 如何在 Mac 使用 ssh 公鑰, 免輸入密碼登入主機 1. Mac 就是 *nix 系統, 跟第一小節作法相同 2. ssh-keygen -t rsa 3. 產生 id_rsa, id_rsa.pub 4. ssh-copy-id alex2@172.104.76.106, 有錯誤, 要加選項 ``` [alexkuo : ~/.ssh ] ➠ $ ssh-copy-id alex2@172.104.76.106 /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 6 key(s) remain to be installed -- if you are prompted now it is to install the new keys Received disconnect from 172.104.76.106 port 22:2: Too many authentication failures Disconnected from 172.104.76.106 port 22 [alexkuo : ~/.ssh ] ➠ $ ``` 5. ssh-copy-id -o IdentitiesOnly=yes alex2@172.104.76.106 ``` [alexkuo : ~/.ssh ] ➠ $ ssh-copy-id -o IdentitiesOnly=yes alex2@172.104.76.106 /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 6 key(s) remain to be installed -- if you are prompted now it is to install the new keys alex2@172.104.76.106's password: Number of key(s) added: 6 Now try logging into the machine, with: "ssh -o 'IdentitiesOnly=yes' 'alex2@172.104.76.106'" and check to make sure that only the key(s) you wanted were added. ``` 6. 回到 NVDA 主機, 查看 `cat ~/.ssh/authorized_keys` 會有新的公鑰加入此檔案, 時間則是此刻 ``` [alex2@nvda ~/.ssh ]$ ll ~/.ssh/authorized_keys -rw------- 1 alex2 admin 2286 4月 20 14:38 /home/alex2/.ssh/authorized_keys ``` 7. ssh -o IdentitiesOnly=yes alex2@172.104.76.106 仍然要輸入密碼 ``` [alexkuo : ~ ] ➠ $ ssh -2 -o IdentitiesOnly=yes alex2@172.104.76.106 alex2@172.104.76.106's password: ``` 8. ssh -o IdentitiesOnly=yes alex2@172.104.76.106 -i ~/.ssh/nvda.alex2.id_rsa ``` [alexkuo : ~ ] ➠ $ ssh -2 -o IdentitiesOnly=yes alex2@172.104.76.106 -i ~/.ssh/nvda.alex2.id_rsa Linux nvda.org.tw 4.18.16-x86_64-linode118 #1 SMP PREEMPT Mon Oct 29 15:38:25 UTC 2018 x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Sat Apr 20 14:08:06 2019 from 122.116.30.130 alex2@nvda:~$ ``` 999. ## 開發者 : clone 並補齊 laravel 設定 ### 把遠端倉庫複製回開發者工作目錄 **重要** 共同開發者只要操作一次 clone #### **@G** 注意 `git clone` 路徑的差異 目前實驗的開發者是 `alex2`, 但 `git author name` 設為 `ben` 便於識別. 先回到自己的家目錄, `git clone g@127.0.0.1:/home/g/repo` 複製遠端倉庫的程式碼回來 > 補充 : `git clone []` > > 也就是說, `git clone g@127.0.0.1:/home/g/repo` 或 `git clone g@127.0.0.1:/home/g/repo benPrj` 皆可, 而後者更方便, 原先 clone 回來預設目錄名稱, 直接指定為自己想要的新名稱. #### 命令 ```bash cd ~ #### **@G** 注意 `git clone` 路徑的差異 git clone g@127.0.0.1:/home/g/repo ls -ld repo mv repo benPrj # 或者直接指定目錄新名稱 git clone g@127.0.0.1:/home/g/repo benPrj cd benPrj ls -l .env ls -l vendor ``` #### 執行結果及說明 ```shell # 本機對本機, 只有 303173 Bytes, 所以 clone 會很快, 咻一下就結束 [alex2@nvda ~ ]$ git clone g@127.0.0.1:/home/g/repo benPrj Cloning into 'benPrj'... The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established. ECDSA key fingerprint is SHA256:kvXp+0IOtRbKfesB+OxXE2WuNlNeE8WmaY32oZIEfGA. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts. remote: Counting objects: 116, done. remote: Compressing objects: 100% (89/89), done. remote: Total 116 (delta 9), reused 116 (delta 9) Receiving objects: 100% (116/116), 236.51 KiB | 0 bytes/s, done. Resolving deltas: 100% (9/9), done. [alex2@nvda ~ ]$ # 此時會 git 會自動幫我們建立一個名為 benPrj 子目錄 [alex2@nvda ~ ]$ ls -ld benPrj/ drwxr-xr-x 12 alex2 admin 4096 4月 19 23:25 benPrj/ # 改成自己喜歡的工作目錄名, 或移動到其他自己方便操作的子目錄之下(例如, 個人偏好放在 ~/jobs/ 之下), 都不會影響開發工作 # git 預設禁止把 .env 檔跟 vendor 目錄放進去追踪, 所以 `沒有此一檔案或目錄`, 都是正常的 [alex2@nvda ~/benPrj ]$ ls -l .env ls: 無法存取 '.env': 沒有此一檔案或目錄 [alex2@nvda ~/benPrj ]$ ls -l vendor ls: 無法存取 'vendor': 沒有此一檔案或目錄 [alex2@nvda ~/benPrj ]$ ``` 首要工作, 就是把 `.env` 跟 `vendor/` 目錄裡的套件程式生出來 #### 命令及說明 ```bash cd ~/benPrj/ composer install npm install cp .env.example .env vi .env php artisan -V ``` #### 執行結果及說明 ```shell # 進工作目錄 [alex2@nvda ~ ]$ cd ~/benPrj/ # 安裝所有 composer 套件 # 要等待一點時間, 讓它把所有套件下載回 vendor/ 子目錄 [alex2@nvda ~/benPrj ]$ composer install Loading composer repositories with package information ...(略) Discovered Package: nunomaduro/collision Package manifest generated successfully. [alex2@nvda ~/benPrj ]$ # 安裝所有 node 套件 # 要等待一點時間, 讓它把所有套件下載回 node_modules/ 子目錄 [alex2@nvda ~/benPrj ]$ npm install # .env 從 .env.example 複製再修改 [alex2@nvda ~/benPrj ]$ cp .env.example .env # 修改正確的 mysql ... 等各項設定 [alex2@nvda ~/benPrj ]$ vi .env # 都完成後, 查看現在版本 [alex2@nvda ~/benPrj ]$ php artisan -V Laravel Framework 5.8.12 [alex2@nvda ~/benPrj ]$ ``` ### git log 查看 我們可以看到由 `Author: alex` 在 `Date: Wed Apr 17 07:41:40 2019 +0800` 創建的 log 資訊 #### 命令 ```shell git log ``` #### 執行結果 ```shell [alex2@nvda ~/benPrj ]$ git log 1 commit 281f0cbb70b2b78e0b65643bc889f6b5adbad636 2 Author: alex 3 Date: Wed Apr 17 07:41:40 2019 +0800 4 5 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex2@nvda ~/benPrj ]$ ``` ### 啟動服務試試 #### 命令 ```shell php artisan serve --host=nvda --port=2019 ``` 進入 [瀏覽器](http://www.nvda.org.tw:2019/) 會出現錯誤, 訊息如下: #### 頁面訊息 ```plaintext RuntimeException No application encryption key has been specified. ``` 這是因為從遠端倉庫 clone 回來時, key 也是被忽略(.gitignore)的文件之一 ### 重新產生 laravel 的 key, 完成後再啟動服務 #### 命令 ```shell php artisan key:generate php artisan serve --host=nvda --port=2019 ``` #### 執行結果 ```shell [alex2@nvda ~/benPrj ]$ php artisan key:generate Application key set successfully. [alex2@nvda ~/benPrj ]$ php artisan serve --host=nvda --port=2019 Laravel development server started: ``` 太棒了, 像日出日落一樣的正常 ### 建立資料庫 一開始建立遠端倉庫用的 laravel 基礎框架時, 可先不處理資料庫設定, 但之後各自要把它完成. 每位開發者有各自開發用資料庫, 公用測試版也有它的資料庫. 當然, 網站正式上線一定會有正式版專用的資料庫. #### 命令及說明 ```shellql # 進入 mysql 命令列, 以下 `MYDATABASE, MYDBUSER, MYDBPASSWORD` 請修改對應, charset 用 utf8mb4, collation 用 utf8mb4_general_ci DROP DATABASE IF EXISTS MYDATABASE; CREATE DATABASE MYDATABASE DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # mysql 5.7 以下可以使用 `WITH mysql_native_password` 或 `WITH sha256_password` 兩種不同的密碼加密方式, 若是 mysql 5.6 以下, 就把這兩個單字移除 CREATE USER 'MYDBUSER'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MYDBPASSWORD'; GRANT ALL ON MYDATABASE.* TO 'MYDBUSER'@'localhost'; FLUSH PRIVILEGES; # 修改 USER 加密方式 ALTER USER 'MYDBUSER'@'localhost' IDENTIFIED WITH sha256_password BY 'MYDBPASSWORD'; ALTER USER 'MYDBUSER'@'localhost' IDENTIFIED WITH mysql_native_password BY 'MYDBPASSWORD'; ``` ### 前置作業 #### 命令及說明 ``` # 修改資料連結的參數 vi .env # 設定 mysql 建立資料庫時的 `MYDATABASE, MYDBUSER, MYDBPASSWORD` vi config/database.php # (可不用修改, 預設 utf8mb4_unicode_ci) mysql 資料庫 collation 預設 utf8mb4_unicode_ci 改為 utf8mb4_general_ci vi config/logging.php # (可暫時跳過) 修改 建立 自定義版本 log # (可暫時跳過) 自定義的單一日期時間 log 檔案, 每一次 request 產生一個記錄 # (可暫時跳過) 複製自定義 log class, app/Loggers/my1LocalLogger.php # (可暫時跳過) 複製自定義 json 輸出 class, app/Loggers/JsonFormatter.php ``` 999. ## 開發者 : clone, clone, clone 所有開發者請現在回到各自家目錄, 開始做 clone 並補齊 laravel 設定, 讓大家版本一致 稍後各自增修同一支程式相同行數位置的內容, 製造 `conflict` 衝突, 然後使用 `merge conflict` 合併衝突來解決. 999. ## 開發者 : 戰鬪, 然後推入遠端倉庫 上一節 `clone 並補齊 laravel 設定` 的基本工作完成後. 單兵開始就戰鬪位置. 現在的開發實作人員的身份仍然為 `alex2` 且 `git name` 是 `ben` ### 開發者 ben 修改或增加檔案 #### 命令 ```bash vi resources/views/welcome.blade.php vi resources/views/abcd.blade.php vi routes/web.php git st -s ``` #### 執行結果及說明 ```shell # 加一些字到 welcome.blade.php [alex2@nvda ~/benPrj ]$ vi resources/views/welcome.blade.php # 84 行 `Laravel` 改為 `Ben's Laravel` # 85 行新增一行

83
84 Ben's Laravel 85

86
# 新增一個 blade 給路由 /a 測試 [alex2@nvda ~/benPrj ]$ vi resources/views/abcd.blade.php # 這個檔案, 只加了一行 1 hello, 你好 # 修改 route 加入一段 /abcd 路由到上面的 abcd.blade.php 的程式 [alex2@nvda ~/benPrj ]$ vi routes/web.php 18 Route::get('/abcd', function () { 19 return view('abcd'); 20 }); [alex2@nvda ~/benPrj ]$ git st -s M resources/views/welcome.blade.php M routes/web.php ?? resources/views/abcd.blade.php [alex2@nvda ~/benPrj ]$ ``` 進入 [首頁](http://www.nvda.org.tw:2019/) 及 [/abcd](http://www.nvda.org.tw:2019/abcd) 完美如昔. 讚, ben 今天完工了, 要把修改及增加的程式碼 `push` 推入遠端倉庫. ### 推入遠端倉庫 推入遠端之前, 本地端仍然要先 `commit` 到本地倉庫. 也才能從本地倉庫推到遠端倉庫. #### 命令 ```bash git st -s git add . git commit -m '動到 2 支 blade (1 舊 1 新) 及 route welcome.blade.php abcd.blade.php 在 routes/web.php 加上 /abcd 路由到上面的 abcd.blade.php 的程式' ``` #### 執行結果 ```shell [alex2@nvda ~/benPrj ]$ git st -s M resources/views/welcome.blade.php M routes/web.php ?? resources/views/abcd.blade.php [alex2@nvda ~/benPrj ]$ git add . [alex2@nvda ~/benPrj ]$ git st -s A resources/views/abcd.blade.php M resources/views/welcome.blade.php M routes/web.php [alex2@nvda ~/benPrj ]$ git commit -m '動到 2 支 blade (1 舊 1 新) 及 route > > welcome.blade.php > abcd.blade.php > 在 routes/web.php 加上 /abcd 路由到上面的 abcd.blade.php 的程式' [master 8aa45d6] 動到 2 支 blade (1 舊 1 新) 及 route 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 resources/views/abcd.blade.php [alex2@nvda ~/benPrj ]$ ``` 推入遠端倉庫, 但我們在執行前後看一下 log, 觀察它的 `(HEAD -> master)` , `(origin/master, origin/HEAD)` 指示器位置 #### 命令 ```bash git ld git push origin master ``` #### 執行結果 ```shell [alex2@nvda ~/benPrj ]$ git ld 1 [#8aa45d6] ben, 2019-04-19 23:47:42 +0800 : (HEAD -> master) 動到 2 支 blade (1 舊 1 新) 及 route 2 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : (origin/master, origin/HEAD) 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex2@nvda ~/benPrj ]$ git push origin master Counting objects: 9, done. Delta compression using up to 2 threads. Compressing objects: 100% (8/8), done. Writing objects: 100% (9/9), 82.58 KiB | 0 bytes/s, done. Total 9 (delta 5), reused 0 (delta 0) To 127.0.0.1:/home/g/repo 281f0cb..8aa45d6 master -> master [alex2@nvda ~/benPrj ]$ git ld 1 [#8aa45d6] ben, 2019-04-19 23:47:42 +0800 : (HEAD -> master, origin/master, origin/HEAD) 動到 2 支 blade (1 舊 1 新) 及 route 2 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex2@nvda ~/benPrj ]$ ``` 完美, 沒有錯誤, 很好, 收工回家. 999. ## 開發者 : 持續的開發, 衝突, 合併, 解決 ### 共同開發者 共同開發者, 第一次也同樣 `clone` 遠端倉庫回自己家, 改目錄名或移到適當位置, 現在以另一開發者 `alex`, `git name` 為 `alex` 開發者身份測試 相同的基本 `clone` 工作及必要設定結束後, 開發者 `alex` 也積極開始工作, 但我們先看看最新的 `git log`, 目前 `alex` 的本地倉庫 #### 執行結果 ``` [alex@nvda ~/ak1 ]$ git ld 1 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : (HEAD -> master, origin/master, origin/HEAD) 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex@nvda ~/ak1 ]$ ``` 現在先 `alex` 也修改 `welcome.blade.php` #### 命令 ```bash vi resources/views/welcome.blade.php # 第 84 行的 `Laravel` 改為 `Alex's Laravel` ...(前略) 83
84 Alex's Laravel 85
...(後略) ``` `alex` 打算收工暫時告一段落, 結束目前的工作, 把程式推入遠端倉庫, 本地端仍然要先 `commit` 到本地倉庫. 也才能從本地倉庫推到遠端倉庫. ### 推入遠端倉庫之衝突發生 #### 命令 ```bash git s git a . git cm '修改 resources/views/welcome.blade.php 的內容' git ld git push origin master ``` #### 執行結果 ``` [alex@nvda ~/ak1 ]$ git s M resources/views/welcome.blade.php [alex@nvda ~/ak1 ]$ git a . [alex@nvda ~/ak1 ]$ git cm '修改 resources/views/welcome.blade.php 的內容' [master c41cf86] 修改 resources/views/welcome.blade.php 的內容 1 file changed, 1 insertion(+), 1 deletion(-) [alex@nvda ~/ak1 ]$ git ld 1 [#c41cf86] alex, 2019-04-17 12:39:14 +0800 : (HEAD -> master) 修改 resources/views/welcome.blade.php 的內容 2 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : (origin/master, origin/HEAD) 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex@nvda ~/ak1 ]$ git push origin master To /home/repo/ ! [rejected] master -> master (fetch first) error: failed to push some refs to '/home/repo/' hint: Updates were rejected because the remote contains work that you do hint: not have locally. This is usually caused by another repository pushing hint: to the same ref. You may want to first integrate the remote changes hint: (e.g., 'git pull ...') before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details. [alex@nvda ~/ak1 ]$ ``` 哇, 爆炸了, 為什麼被拒絕 `! [rejected]` , 注意同一行最後那個括號裡的字 `(fetch first)`, 此刻 `alex` 並不知道 `ben` 先前已 push 過, 而且剛好也是都改到相同的一個檔案. ### fetch first 既然如此, 就按照它的指示, 開始操作. `fetch` 完成後, 還不能 `push`, 會得到相同的錯誤. 緊接著要做的是用合併解決衝突. #### 命令 ```bash git fetch origin master git merge origin/master ``` #### 執行結果 ```shell [alex@nvda ~/ak1 ]$ git fetch origin master [alex@nvda ~/ak1 ]$ git merge origin/master Auto-merging resources/views/welcome.blade.php CONFLICT (content): Merge conflict in resources/views/welcome.blade.php Automatic merge failed; fix conflicts and then commit the result. [alex@nvda ~/ak1 ]$ ``` 注意 `CONFLICT (content): Merge conflict in resources/views/welcome.blade.php` , 它指出衝突的來源, 其實就是兩個開發者都改了同一個 `resources/views/welcome.blade.php` 檔案, 那麼就解決它吧. ### 解決 merge 的 CONFLICT 衝突 #### 命令 ```shell vi resources/views/welcome.blade.php ``` #### 執行結果 ```html 83
84 <<<<<<< HEAD 85 Alex's Laravel 86 ======= 87 Ben's Laravel 88

89 >>>>>>> origin/master 90
``` 打開衝突發生的檔案, 會看到 第 84 行 `<<<<<<< HEAD` 到 86 行 `=======` 之間的程式碼, 表示現在 `alex` 自己開發版本修改的內容. 第 86 行 `=======` 到 89 行 `>>>>>>> origin/master` 之間的程式碼, 表示遠端倉庫最後被 `ben` `push` 上傳的內容. `alex` 此刻要呼叫 `ben` 來解決問題, 或者找 `此專案的總工程師` 來解決...... 經過溝通後, 程式修改成另一版本, 原先 `<<<<<<<`, `=======`, `>>>>>>>` 標記的三行, 都要刪除 #### 程式修改完美協調版本 ```html 83
84 NVDA Laravel 85

86
``` ### 解決衝突後, 再度 git #### 命令 ```bash git s git a . git s git cm '解決 resources/views/welcome.blade.php 衝突' git ld git push origin master git ld git push origin master ``` #### 執行結果 ```shell [alex@nvda ~/ak1 ]$ git s A resources/views/abcd.blade.php UU resources/views/welcome.blade.php M routes/web.php [alex@nvda ~/ak1 ]$ git a . [alex@nvda ~/ak1 ]$ git s A resources/views/abcd.blade.php M resources/views/welcome.blade.php M routes/web.php [alex@nvda ~/ak1 ]$ [alex@nvda ~/ak1 ]$ git cm '解決 resources/views/welcome.blade.php 衝突' [master d826a09] 解決 resources/views/welcome.blade.php 衝突 [alex@nvda ~/ak1 ]$ [alex@nvda ~/ak1 ]$ git ld 1 [#d826a09] alex, 2019-04-17 13:06:31 +0800 : (HEAD -> master) 解決 resources/views/welcome.blade.php 衝突 2 [#c41cf86] alex, 2019-04-17 12:39:14 +0800 : 修改 resources/views/welcome.blade.php 的內容 3 [#054f3fe] ben, 2019-04-17 12:24:53 +0800 : (origin/master, origin/HEAD) 動到 2 支 blade (1 舊 1 新) 及 route 4 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex@nvda ~/ak1 ]$ git push origin master Counting objects: 10, done. Delta compression using up to 2 threads. Compressing objects: 100% (9/9), done. Writing objects: 100% (10/10), 931 bytes | 0 bytes/s, done. Total 10 (delta 6), reused 0 (delta 0) To /home/repo/ 054f3fe..d826a09 master -> master [alex@nvda ~/ak1 ]$ [alex@nvda ~/ak1 ]$ git ld 1 [#d826a09] alex, 2019-04-17 13:06:31 +0800 : (HEAD -> master, origin/master, origin/HEAD) 解決 resources/views/welcome.blade.php 衝突 2 [#c41cf86] alex, 2019-04-17 12:39:14 +0800 : 修改 resources/views/welcome.blade.php 的內容 3 [#054f3fe] ben, 2019-04-17 12:24:53 +0800 : 動到 2 支 blade (1 舊 1 新) 及 route 4 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex@nvda ~/ak1 ]$ git push origin master Everything up-to-date [alex@nvda ~/ak1 ]$ ``` 最後看到的 log , ` alex` 提交了兩次, 一次改檔本地提交, 另一次是解決衝突. 好了, 終於可以回家了 :-( 999. ## 每天工作前第一件事? ### 每天工作前第一件事? 是什麼, 就是把遠端倉庫裡的最新資料拉回來 :-D, 拉回來後, 該解決衝突就馬上解決 > **備註** : git fetch + git merge 等同於 git pull。 目前再度回到 `ben` 的家 #### 命令 ```bash git ld git pull origin master git ld ``` #### 執行結果 ```shell [alex2@nvda ~/benPrj ]$ git ld 1 [#054f3fe] ben, 2019-04-17 12:24:53 +0800 : (HEAD -> master, origin/master, origin/HEAD) 動到 2 支 blade (1 舊 1 新) 及 route 2 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex2@nvda ~/benPrj ]$ git pull origin master remote: Counting objects: 10, done. remote: Compressing objects: 100% (9/9), done. remote: Total 10 (delta 6), reused 0 (delta 0) Unpacking objects: 100% (10/10), done. From /home/repo 054f3fe..d826a09 master -> origin/master Updating 054f3fe..d826a09 Fast-forward resources/views/welcome.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) [alex2@nvda ~/benPrj ]$ git ld 1 [#d826a09] alex, 2019-04-17 13:06:31 +0800 : (HEAD -> master, origin/master, origin/HEAD) 解決 resources/views/welcome.blade.php 衝突 2 [#c41cf86] alex, 2019-04-17 12:39:14 +0800 : 修改 resources/views/welcome.blade.php 的內容 3 [#054f3fe] ben, 2019-04-17 12:24:53 +0800 : 動到 2 支 blade (1 舊 1 新) 及 route 4 [#281f0cb] alex, 2019-04-17 07:41:40 +0800 : 創立遠端倉庫用的 laravel 基礎框架 5.8.12 [alex2@nvda ~/benPrj ]$ ``` 現在啟動服務, 進入 [瀏覽器](http://www.nvda.org.tw:2019/), 看看首頁內容, 衝突解決了. 999. ## 實用相關資訊 ### 本地端設定值 #### 命令 ```bash cat .git/config ``` #### 執行結果 ```shell [alex@nvda ~/ak1 ]$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = /home/repo/ fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [alex@nvda ~/ak1 ]$ ``` 注意 `[remote "origin"]` 跟 `[branch "master"]` 這兩段 `[core]` 這裡看到的是 `本地倉庫 local 之值`, 可比對 `cat ~/.gitconfig 的 global 值`, 常用的我們都會設定到 global, 除非有特定目的才會設在這裡. ### 在本地倉庫端顯示 fetch, push 遠端倉庫的資訊 #### 命令 ```bash git remote -v ``` #### 執行結果 ```shell [alex@nvda ~/ak1 ]$ git remote -v origin /home/repo/ (fetch) origin /home/repo/ (push) [alex@nvda ~/ak1 ]$ ``` ### 好用的連結 * [Git 面試題](https://gitbook.tw/interview) * [四種將分支與主線同步的方法](https://cythilya.github.io/2018/06/19/git-merge-branch-into-master/) * 以上這兩篇文章寫得不錯, 跟我們此篇內容有比較多的關聯, 大家找時間把它精讀. * [Git的奇技淫巧 - 簡體中文](https://github.com/521xueweihan/git-tips) 此為老外整理 [Most commonly used git tips and tricks.](https://github.com/git-tips/tips) 的簡體中文版, 很實用, 極具參考價值. 999. ## 本章總結 ### 本章使用 git 命令總結 ```bash ssh-keygen -t rsa # 產生個人公鑰及私鑰 git init --bare # 遠端倉庫初始化 git remote add origin g@127.0.0.1:/home/g/repo # 設定 git 本地倉庫到遠端倉庫的連結, ssh 共用帳號 g git remote add origin 127.0.0.1:/home/repo # 設定 git 本地倉庫到遠端倉庫的連結, 原始版 git clone g@127.0.0.1:/home/g/repo myPrj # 複製遠端倉庫回家, 指定目錄名稱, ssh 共用帳號 g git clone /home/repo myPrj # 複製遠端倉庫回家, 指定目錄名稱, 原始版 git push origin master # 本地倉庫(分支 master)提交後, 推入遠端倉庫(origin 的分支 master) git pull origin master # 拉回遠端倉庫(origin 的分支 master)最後版本到本地倉庫(分支 master) git fetch origin master # 取得遠端倉庫分支 master 的資料 git merge origin/master # 合併本地倉庫分支 origin/master 的程式碼 ```