Git command note
版本控管功能多是好事,但指令多就容易出錯,避免悲劇發生,指令小抄保平安!.ignore 各種語言 & framework範本
https://github.com/github/gitignore
符號
- HEAD^^ #HEAD前一代的前一代
- HEAD~2 #同 ^^,HEAD 前二代
- HEAD~5..HEAD~2
- HEAD~5...HEAD~2
- HEAD@{3} #HEAD的異動編號,使用 git reflog 查看
設定
- .gitconfig 路徑
- Mac/Linux
- System(底層):/usr/local/git/etc/gitconfig
- 查詢:git config --show-origin --get credential.helper
- Global(使用者): ~/.gitconfig
- Local(專案): ./git/config
- windows
- C:\users\[user]\.gitconfig
- 查詢完整設定
- git config --list
- 使用者名稱
- git config --global user.name "First Last"
- 電子郵件
- git config --global user.email "[email protected]"
- 套用到目前 commit
- git commit --amend --reset-author
- 指令縮寫
- git config --global alias.[縮寫] [method]
- 自動儲存帳號與密碼
- 永久
- git config --global credential.helper store
- 暫存 15 分鐘
- git config --global credential.helper cache
- 暫存 60 分鐘
- git config credential.helper 'cache --timeout=3600'
- 永久,用 Mac 鑰匙圈加密、存取
- git config --global credential.helper osxkeychain
- 解決 osxkeychain 一直要求帳密
- 在 finder 搜尋 Keychain Access,中文為「鑰匙圈存取」
- 在 app 搜尋 git repo 的 domain,注意「位置」,將對應的 key 刪除
- Pull 專案,會跳出輸入密碼,打 mac 登入時用的密碼
建立 repo
- git init <dir>
- 無
- 有 working directory
- --bare
- 無 working directory,純粹 .git 結構
- --mirror
- 無 working directory,純粹 .git 結構
- 可以 base on 某個 repo,並使用 git fetch 與 base repo 同步
權限
- init shared permissions
- chgrp -R foo repodir # set the group
- chmod -R g+rw repodir # allow the group to read/write
- chmod g+s `find repodir -type d` # new files get group id of directory
- lock
- repo 增加檔案 /hooks/update
#!/bin/sh
# lock the myfeature branch for pushing
refname="$1"
if [[ $refname == "refs/heads/myfeature" ]]
then
echo "You cannot push to myfeature! It's locked"
exit 1
fi
exit 0
新專案
- 空資料夾
$ git clone ./repo ./target_dir
- 有資料
$ git init $ git checkout -b master #可略 $ git remote add origin repo_path
- 推第一版
$ git push -u origin master
Repository操作
- 更換專案的 repo Url
- git remote set-url origin newUrl
branch操作
遠端
- 新增
- git push -u origin new_branch
- 查詢
- git branch -r
- 刪除
- git push origin :new_branch
- 更名
- git push -u origin old_branch:new_branch
- 再刪掉 old_Branch
- 修剪(refreash)
- git remote prune origin
本地
- 新增/複製 分支
- git checkout -b new_branch(新) origin/new_branch(來源)
- 新增空白分支
- git checkout -b --orphan <new_branch>
- 查詢
- git branch
- 刪除
- git branch -d
- -D 強制刪除
- 更名
- git branch -m newBranch rename
- -M 即使新名稱存在仍強制更名
- 覆蓋遠端
- git push remote branch --force
checkout
- branch
- git checkout new_branch
- git checkout new_branch origin/new_branch
- 新增空白分支
- git checkout -b --orphan <new_branch>
- 切換失敗
- git checkout -b branch origin/branch
- 取自己分支修改前的檔案
- git checkout -- *
- 不切換,直接取其她分支檔案
- git checkout branch commit filename
- git checkout branch -- aa.php
- 拉前一個版本的某個檔案
- git checkout HEAD~1 -- path
- 使用 reset --hard HEAD 還原
- 退回前一版,且能再次 commit
- git checkout HEAD~1 -- .
pull
- git pull
- 從 Remote 拉下來 merge,並產生新 commit "Merge branch 'master'..."
- git pull --rebase
- 可讓 tree 更乾淨
- 比對 remote 新增的 commit,直接併入,不產生新的 Merge commit
- 若有衝突,須每個 commit 一一排除
- 將分支 commit 蓋回此線
- git pull 來源repo 來源分支
- ex.git pull origin master
diff
- git diff HEAD filepath
clean
- git clean -fdx #強力清除 untracked file
- f=檔案, d=資料夾, X=忽略的檔案, x=忽略&非忽略的檔案
add
- git add -A . #將 delete 的部分也加入清單
- git add -u #只加 modify 檔案
- git add filename
- git reset HEAD filename #將某檔案從 add 清單中移除
commit
- 交付
- git commit -a -m "message" #交付全部,並寫入 commit 註解
- 改註解
- git commit --amend
- 修改後 :wq! 儲存離開
- 解除
- git reset --soft HEAD~1 #刪除最近1期commit
- 解除 commit,並將所有檔案回復到 git add 的狀態
- 查未 push
- git cherry -v #查詢未 push 的 commit
- git log master ^origin/master #詳細
- 查看檔案內容
- show commitHash:filepath
- 匯出檔案
- show commitHash:filepath > filename
- 複製其他分支 commit
- git cherry-pick ab00d1
- #情境:要上特定幾個 commit 到 online,可以將指定 n 個櫻桃(commit) 挑到 release 的 branch 中
- 刪除遠端
- git reset --hard <last_working_commit_id>
- git push --force
- # 小心別誤砍其他人的 code
reset(重置)
- git reset HEAD #放棄全部 add file ,或刪除指定 add file
- git reset --soft HEAD #刪除 commit
- git reset --soft HEAD~1 #解除 commit,並將所有檔案回復到 git add 的狀態
- git reset --hard HEAD #放棄所有檔案變更
- git reset --hard HEAD~1 #刪除 commit & 退回(rollback)到指定的前一版本
- 若未 push,可用 git pull 還原
- (link)
revert(恢復)
- 與 reset 差異
- 回復的內容,會新建立一個 commit
- reset 在 merge 時,會被同 base 的 branch 填充重置掉的 commit?
mv(移動)
- *移動檔案盡量使用此指令
- git mv path new_path
rm
- rm #shell 刪除文件
- git rm --cached #刪除 git 追蹤文件
- git rm #刪除 git 追蹤文件、並刪除文件
- -f 強制, -r 資料夾遞迴
merge
- 合併
- git merge branch
- --no-commit
- --squash #不會產生 commit
- --no-ff
- 取消合併
- git reset --merge ORIG_HEAD
- 出現Conflit,想取消合併
- git reset --hard HEAD
- 解完 Conflit
- 只需重新 add & commit
stash
- git stash -a #將 add & delete 等異動檔案暫存
- git stash list #列出 stash 清單
- git stash apply #讀出指定 stash
- git stash pop #讀出並刪除指定 stash
- git stash drop stash@{1} #刪除指定 stash
log
- git log -2 #顯示最近2個 commit
- git log --name-only #只顯示 commit file list
- git log origin/master..branch_name #看remote log
- git log -stat
- git log filepath #該檔案的所有 log
- git log --grep pattern #查 message 符合 pattern 的 log
reflog
- git reflog brnach1 #顯示 branch1 歷史交付的紀錄
submodule
依附在主專案下,情境通常是 include 使用別人的專案使用,每次 clone 專案,就需下 init、update submodule,
主專案會紀錄並「鎖定」submodule 版本,每次更新 submodule 務必 commit 版本號
- 新增
$ git submodule add repo_addr [folder]
#會多出 .gitmodules,也會新增在 .git/config 中
$ git status
# new file: .gitmodules
# new file: 子模組folder
$ git add .
#方法一
$ git clone repo_addr --recursive [folder] #直接把所有子模組拉下來,效果同方法二
#方法二
$ git submodule init #關聯到 .git/config 中,只需在專案初始時執行一次
$ git submodule update --recursive
$ git submodule status #看全部子模組版本
$ cd moduleFolder
$ git pull
#一次更新全部
$ git submodule foreach --recursive git pull origin master
$ nano .gitmodules #手動修改
$ git submodule sync
$ git submodule deinit -f moduleFolder #解除 .git/config 關聯
$ git rm --cached moduleFolder
$ rm -rf moduleFolder
$ nano .gitmodules #手動移除該子模組
出現 No submodule mapping found,請看最下方「常見狀況」
檔案清單
- git ls-files #全部檔案
顯示檔案內容
- git show branch:filepath
archive
- 包成壓縮檔
- git archive -o patch.zip HEAD $(git diff --name-only [id])
- export 檔案
- git archive HEAD $(git diff --name-only [id]) | tar -x -C ./patch
- git archive HEAD $(git diff HEAD~1 HEAD~2 --name-only) | tar -x -C 絕對路徑
- ~1 為 base commit,目標的編號減 1,如果是目前的,就不用加 ~
- ~2 為 target commit,要匯出的 commit 排序編號同 git log -2
- 可以是大範圍,同個檔案,會以 base commit 為準,也就是會抓較近期的
rebase (link)
- git rebase -i commit_id
- commit_id 這次要編輯的範圍,起始 commit(舊)
- 編輯器上到下為 舊->新 (與 log 相反)
- 將 pick 改為 s(同squash) 可以合併掉該 commit 到舊一版 commit 中
- git rebase -i HEAD~4
- 合併最近4個 commit
- git rebase --abort #取消
- 解衝突
- git add filename
- git rebase --continue
- *建議使用在 push 前整理分支用! 而用在 push 後容易出現令人沮喪的麻煩
lock
- .git/index.lock
.gitignore
- 推薦 script
- phpstorm
- android
- mac
- ...
- 編輯完後,執行 git clean 指令
[alias]
- export file
- git config --global alias.ex '!f() { mkdir -p $2;git archive HEAD $(git diff HEAD~$(($1-1)) HEAD~$1 --name-only) | tar -x -C $2;}; f'
- 指令:git ex 版本數量 filepath
- undo stash
- git config --global alias.stash-unapply '!git stash show -p $1 | git apply -R'
- 還原變更&清除
- git cls --global alias.cls '!git reset --hard HEAD;git clean -f"
File status lifecycle (圖片來自 link)
Git server (ubuntu)
- 權限控管 Gitolite
- GitWeb
- 使用 nginx htpasswd
- linux下指令 htpasswd /etc/nginx/.htpasswd <username>
開發流程
- Github Flow
- Create A Branch (建立一個分支)
- Add Commits (新增 Commits)
- Open a Pull Request (開一個推送請求PR)
- Discuss And Review (討論及審查)
- Deploy (部署)
- Merge (合併)
- Gitlab Flow
- 中文說明
- upstream first policy
- git cherry-pick 機制
- git merge --no-ff 或 git merge --squash
- Git Flow
- 版控基本規劃(過去實行筆記)
- 一個 project 一個 repo
- 環境 branch
- master - 上線版
- dev - 開發版
- beta - 測試版
- stage - 上線前版
- DEV - 開發環境
- SIT - 系統整合測試
- UAT - 使用者(業主)驗收測試
- PEM - 性能評估測試(壓測)
- SIM - 仿真
- 事件 branch
- pj_xxx - project 中的某個獨立小專案
- hotfix_xxx - 上線後有問題,當日需修復的 bug
- regular_xxx - 程式碼重構,非急迫性質
- feature_xxx - 小功能
- workflow
- leader 建立 repo、環境 branch
- Senior 將 base code Commit 到 dev
- 小組從 dev 再各自開 feature_xx
- 小組完成後,Merge 回 dev並測試
- dev 環境測試有問題,則修正該 pj_xx,完成後重新 Merge 一次
- 上 beta 環境,依照小 feature_xx 的相依程度,分開或同時上
- beta 環境測試有問題,改完再從 dev 開始測
- stage 同理,並非 merge 整個 beta,而是個別 merge feature branch
- 若該階段所有小 pj 完成,則 master 直接 merge stage
- 上線後有問題,開 hotfix,從 dev 向上測,但優先度高
如何在已經存在的 project 套用 repo
$ cd 專案目錄內
$ git init
$ git add .
$ git commit -m "base version"
$ git remote add origin repo網址
$ git push -u origin master
- 切分支
$ git checkout -b dev
$ git push -u origin dev
在 GitHub 上 Fork 的專案,如何定期更新
- 一開始幾種方式變成自己的 code
- github 上直接 Fork 成為自己的 project
- 或用 clone,再改寫 remote origin
- 或建一個 repo,再做以下動作
- 概念
- 2個 remote,一個是 origin(自己 fork下來的),另一個是 upstream(原生專案更新用)
- 更新 upstream 後,合併回 origin
- 相關資料
- Forking a Github repo to Bitbucket (link)
- 操作
- 建立
- 日常維護
- 刪除上游
$ git #先 init 或 clone origin 專案
$ echo " " > README.md
$ git add .; git commit -m "README.md"
$ git remote add upstream https://github.com/fork來源作者/fork來源專案名稱
$ git pull upstream #後面可帶指定 branch
$ git merge upstream/分支名稱 --squash #merge 不產生其他 commit
或
$ git rebase upstream/master #將 remote 新 commit 貼到 local,並產生 n 個 cherry
$ git #可考慮用 rebase 合併,參考下方維護
$ git push -u origin master
$ git pull upstream
$ #git reset --hard HEAD #放棄未 commit 的所有資料
$ git merge upstream/分支名稱 --squash #merge 不產生其他 commit
$ #排除衝突 using 'Theirs'
$ git push
$ vi .git/config
$ #刪除 upstream
將 local 專案(含所有分支)轉到 bitbucket
$ cd 已存在的專案folder
$ git remote add bitbucket bitbucket專案網址 #增加一個remote
$ git push --all bitbucket #將全部分支推上去
$ git push --tags bitbucket #將全部tag推上去
*.可直接在 bitbucket 使用 import repository,輸入 old project & auth 即可
完整轉移 Repository
$ git clone --mirror [email protected]:myteam/myrepo.git
$ cd myrepo
$ git remote set-url --push origin [email protected]:newteam/myrepo.git
$ git push --mirror
Merge 出錯,如何還原?
- 通常是 merge 時有問題,將 merge 前的版本打包出來
- shell script 出現 no found (參考)
- 先檢查文件 Line Separator,是 CRLF(windows) or CR(MAC)
- 使用 git config core.autocrlf ,看是否回傳 true
- 如果你專案都是 CRLF,那就設為 false,若不是則設 true
- 刪除專案,若只對此專案修改,請保留 .git,其他 folder 清掉
- 重新 pull 或 clone 資料
- No submodule mapping found in .gitmodules for path 'path/myFolder'
- 使用 git rm --cached path/myFolder
#三選一
$ git config --system core.autocrlf true #對全系統
$ git config --global core.autocrlf true #對此user
$ git config core.autocrlf true #對此專案
推薦文章
- Docker — 從入門到實踐
- Git 30天精通
- Git 情境劇
- rebase 完整教學
- Git 互動教學
git merge 與 rebase 的觀念與實務應用
https://www.slideshare.net/WillHuangTW/git-merge-rebase
Git command note
Reviewed by Wild
on
7/15/2015 05:39:00 下午
Rating:
沒有留言:
沒有Google帳號也可發表意見唷!