最後更新: 2024-10-30
介紹
git 係一個 source code management system
目錄
- 安裝
- HEAD / master / origin
- 最常用功能一覽
- 設置自己的身份
- Configure Git
- Save username and password(Login)
- Importing a new project
- Branches
- checkout a file
- hash checkout
- Tag
- To compare two tags
- Undo
- Move
- .gitignore
- Cleanup - git gc
- GUI Tools
- git setttings
- Environment Variables
- To clear out the history of a git/github repository
- github raw download file
- Doc
安裝
# Ubuntu
apt-get install git
# Version
git --version
git version 1.7.9.5
HEAD / master / origin
HEAD [branch]:
My repo currently pointing at (Most of the time HEAD points to the latest commit in your branch)
master:
"master" means "the main branch", it is considered the definitive view(website) of the repo.
# default branch that git creates for you when first creating a repo (git init)
origin:
"origin" 是預設的 remote repos 名稱
=> That remote repo is almost always called origin
設定 origin
- git clone 時會自動設定它
- git remote add origin https://github.com/USERNAME/REPOS.git
你可以使用 "origin" 來引用它
i.e.
git push origin master # 將 local 的 master 分支推送到 origin(它是在 remote 的)
How Git stores its data
Git doesn’t store data as a series of changesets or differences, but instead as a series of snapshots.
Element checksum: SHA-1 hash
"git commit"
會新建 3 個物件
* blob 物件 ( the contents of each of your files) [SHA-1]
* tree 物件 ( directory and specifies which file names )[SHA-1]
* commit 物件 ( metadata ) [SHA-1]
commit 1 --> commit 2 --> commit 3 | | ... tree tree | | blob blob
Fast-forward
C2 <- C4
you merged in was directly ahead of the commit C2 you’re on,
Git simply moves the pointer forward.
Workflows
With Git, you don’t have to deploy your fix along with the iss53 (for new feature)changes you’ve made,
and you don’t have to put a lot of effort into reverting those changes before you can work on applying your fix to what is in production.
All you have to do is switch back to your master branch.
為 production 建立 hotfix 先, 不在新功能上做 hotfix
最常用功能一覽
Clone (download) a new repository
* clone 一次就有齊所有 branch (whole repository)
git clone [git/https]://?????/?????.git
e.g.
# 之後會有 Folder "ngx_pagespeed"
git clone https://github.com/pagespeed/ngx_pagespeed.git
List branch
shows all
git branch -a
2.1.3
master
* stable
remotes/origin/2.1.3
remotes/origin/CDN
remotes/origin/HEAD -> origin/master
remotes/origin/jst
remotes/origin/master
remotes/origin/nginx-1.0
remotes/origin/nginx-1.2
remotes/origin/nginx-1.2.0
remotes/origin/nginx-development
remotes/origin/revert-500-robin
remotes/origin/stable
最尾係 branch 名
查看已訂閱了的 branch
git branch
* 2.1.3 # "*" 代表在此 branch master
Show remote
Manage the set of remotes repositories whose branches you track.
git remote [show]
origin # 起源
git remote -v
origin https://git.php.net/repository/php-src.git (fetch) origin https://git.php.net/repository/php-src.git (push)
git remote show origin
* remote origin Fetch URL: https://git.php.net/repository/php-src.git Push URL: https://git.php.net/repository/php-src.git HEAD branch: master Remote branches: PEAR_1_4DEV tracked PECL tracked PECL_4_3 tracked PECL_OPENSSL tracked PHAR_1_2 tracked PHP-4.0 tracked PHP-4.0.5 tracked PHP-4.0.6 tracked ............................. Local branches configured for 'git pull': PHP-7.0.16 merges with remote PHP-7.0.16 PHP-7.0.17 merges with remote PHP-7.0.17 master merges with remote master Local refs configured for 'git push': PHP-7.0.16 pushes to PHP-7.0.16 (up to date) PHP-7.0.17 pushes to PHP-7.0.17 (local out of date) master pushes to master (local out of date)
Checkout a branch
git checkout 2.1.3
Revert your changes
# 比如刪除錯或修改錯的 file 想 revert (新增的 File 依然存在)
git checkout .
Clone the one you already have on your hard disk
git clone /path/to/foo
Update
cd ngx_pagespeed
git pull
* pull = fetch + merge
e.g. ngx_pagespeed
Already up-to-date.
e.g. tengine
remote: Counting objects: 20, done. remote: Total 20 (delta 10), reused 10 (delta 10), pack-reused 10 Unpacking objects: 100% (20/20), done. From https://github.com/alibaba/tengine 2069159..b2531ec master -> origin/master Already up-to-date.
force “git pull” to overwrite local files
# git reset --hard origin/<branch_name>
git reset --hard
HEAD is now at 37eb1e4 prepare final versions
pull 拎的 URL
# Git stored the location of repository in the repository configuration, and that location is used for pulls:
cd testproj/
git config --get remote.origin.url
https://[email protected]/datahunter88/testproj.git
git fetch
git fetch [<options>] [<repository> [<refspec>…]]
Fetch branches and/or tags (collectively, "refs") from one or more other repositories
When no remote is specified, by default the origin remote will be used,
unless there’s an upstream branch configured for the current branch.
# Alice can peek at what Bob did without merging first, using the "fetch" command;
# This operation is safe even if Alice has uncommitted local changes.
alice$ git fetch /home/bob/myrepo master
# -p, --patch <= Generate patch
# log use "-p" see complete diffs at each step
alice$ git log -p HEAD..FETCH_HEAD
Check Status
cd ngx_pagespeed
git status
Opts
-v, --verbose
e.g. ngx_pagespeed
On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean
e.g. tengine
# On branch 2.1.3 nothing to commit (working directory clean)
clean
git clean -xdf # Remove untracked files from the working tree
-f # --force
-d # Remove untracked directories in addition to untracked files.
-x # Don’t use the standard ignore rules read from .gitignore
# ignored files are also removed (build products)
-n # --dry-run
Untracked files
(files that didn't originally exist in the tree, ones you created and not edited)
設置自己的身份
# 設定自己的名稱及E-Mail
# Global Settings
git config --global user.name "Your Name"
git config --global user.email "[email protected]"
# Per User (Per Folder) Settings
git config user.name "Your Name"
git config user.email "[email protected]"
Checking
git config user.name
git setting
git config --global user.name "x"
git config --global user.email "x@y"
Configure git
# Git 用此 command 設定
git config
# Configure File
/etc/gitconfig # system
Contains values applied to every user on the system and all their repositories.
(If you pass the option "--system" to git config, it reads and writes from this file specifically.)
~/.gitconfig or ~/.config/git/config # user(you)
Git read and write to this file specifically by passing the "--global" option
.git/config # repository
You can force Git to read from and write to this file with the "--local" option
# Opts
- -l, --list # list all current config
- -e, --edit
- --unset # remove a variable: name [value-regex]
- --add # add a new variable: name value
- --get # get value: name [value-regex]
- --global # For writing options: write to global "~/.gitconfig" file rather than the repository".git/config"
# Usage
# List all setting (--list)
# global setting
git config -l
user.name=Tim [email protected]
P.S.
到 repository 時會 show 埋 local setting
# local setting
cd repository
cat .git/config
# Files
~/.gitconfig
[user] name = Tim email = [email protected]
# Alias
# git ci,取代輸入git commit
$ git config --global alias.ci commit
$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.br branch
.gitconfig
[alias] ci = commit st = status co = checkout br = branch
# 常用設定
editor
git config --global core.editor vim
merge tool
git config --global merge.tool vimdiff
push.default
# 不設定 push.default 會令每次 git push 有 warning
# 'matching': git will push local branches to the remote branches that already exist with the same name.
# 'simple' (Git 2.0 default): more conservative behavior, which only pushes the current branch to the corresponding remote branch
that 'git pull' uses to update the current branch.
git config --global push.default matching
# 自動補齊
source /etc/bash_completion.d/git-prompt
Save username and password(Login)
https 與 ssh
git 支援兩種 protocol
ssh://[email protected]/username/repo.git
https://github.com/username/repo.git
credential.helper
* store 及 cache 都是由 push 引發保存
helper: store
# Helper to store credentials on disk( ~/.git-credentials ) <-- unencrypted
git config credential.helper store # per repository config
.git/config
... [credential] helper = store
cat ~/.git-credentials
https://username:[email protected]
helper: cache
# stored credentials never touch the disk, and are forgotten after a configurable timeout
# accessible over a Unix domain socket
git config credential.helper 'cache [options]'
# Default options:
- --timeout 900
- --socket ~/.git-credential-cache/socket
保存 global 設定
git config --global credential.helper 'cache --timeout 300'
exit early
git credential-cache exit
Create a new repository
git clone https://gitlab.com/datahunter88/testproj.git
cd testproj
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
# -u, --set-upstream
# 為成功的 push 及 pull, 加 tracking
# 當沒有 set 時, 就會見到
There is no tracking information for the current branch. Please specify which branch you want to merge with.
* 要整個 push 動作完成後在 remote 才 display update
# set tracking only
git branch --set-upstream-to=origin/<branch> master
git add
# all *.txt files under Documentation directory and its subdirectories:
git add Documentation/\*.txt
# it does not consider subdir/git-foo.sh (lets the shell expand the asterisk)
git add git-*.sh
Importing a new project
# 把新 project 解開
$ tar xzf project.tar.gz
$ cd project
# 建立 .git/
$ git init
Initialized empty Git repository in /home/tim/myapp/.git/
.git/ 內有
branches config description HEAD hooks info objects refs
# remote
git remote add origin https://gitlab.com/datahunter88/testproj.git
# 為當前的狀態建立 snapshot
# git add filename
# "." = all files & subdirectory under the current directory
$ git add .
# 保存 "git add ." 所建立的狀況 (把 diff 放入 index Folder)
# git commit [-m "string"]
$ git commit -m "Initial app setup."
25 files changed, 19319 insertions(+) create mode 100644 .gitignore create mode 100644 README.md
# 查看 Status (看到那 file modify 了而未 commit)
git status
# push it in master branch
git push -u origin master
# Viewing project history
# 新到舊的順序列出儲存庫的提交的歷史記錄
git log
git log --pretty=oneline --since='5 minutes ago'
git log --pretty=oneline --until='5 minutes ago'
git log v2.5..v2.6 # commits between v2.5 and v2.6
git log v2.5.. # commits since v2.5
git log stable..master # will list commits made in the master branch but not in the stable branch
# show: get more info
git show commit-id
git show first-few-characters-commit-id
git show HEAD # the tip of the current branch
git show HEAD^ # to see the parent of HEAD
git show HEAD^^ # to see the grandparent of HEAD
git show v2.5:Makefile
git-commit
# all in one step
# automatically notice any modified (but not new) files, add them to the index, and commit,
git commit -a
# comment from file
# Take the commit message from the given file. Use - to read the message from the standard input.
-F <file> / --file=<file>
Branches
List, create, or delete branches.
Help: man git-branch
# view local branch 的情況
git branch
* master
# rename local repos
# -M Shortcut for --move(-m) --force(-f)
# --move(-m) Move/rename a branch
# Without -f, git branch refuses to change an existing branch
git branch -M main
# 查看 remote branch 的情況
# -r, --remotes <= List or delete (used with -d) the remote-tracking branches
git branch -r
# Create local "experimental" branch
git branch experimental
# switch to the experimental branch
git checkout experimental
Remark: Create & Switch to new branch
# "-b" a new branch to be created and then checked out
git checkout -b [name_of_your_new_branch]
# Add a new remote for your branch
$ git remote add [name_of_your_remote]
# Push the branch on new github
$ git push origin [name_of_your_new_branch]
OR
$ git push [name_of_your_new_remote] [name_of_your_branch]
# remark - 查看 branch 的對應
git remote show origin
Remote branches: mybranche-v1 tracked mybranche-v2 tracked mybranche-v3 tracked master tracked Local branch configured for 'git pull': master merges with remote master Local refs configured for 'git push': mybranche-v1 pushes to mybranche-v1 (up to date) mybranche-v2 pushes to mybranche-v2 (up to date) mybranche-v3 pushes to mybranche-v3 (up to date) master pushes to master (up to date)
# Go back master
git checkout master
# To merge the changes made in experimental into master
git merge experimental
# To delete the local branch use:
When you're dealing with deleting branches both locally and remotely,
keep in mind that there are 3 different branches involved:
* The local branch X.
* The remote origin branch X.
* The local remote-tracking branch origin/X that tracks the remote branch X.
# -d option is an alias for --delete
# which only deletes the branch if it has already been fully merged in its upstream branch.
git branch -d the_local_branch
i.e. # Delete "2.0.21" branch
git branch -d 2.0.21
Deleted branch 2.0.21 (was cc8d8b6).
i.e. # Delete "2.0.21" master
git branch -d master
warning: deleting branch 'master' that has been merged to 'refs/remotes/origin/master', but not yet merged to HEAD. Deleted branch master (was f3cd80d).
# -D, which is an alias for --delete --force,
# which deletes the branch "irrespective of its merged status.
git branch -D master
# Delete Remote Branch
# --delete - All listed refs are deleted from the remote repository.
git push origin --delete <branch_name>
# # All remote-tracking branches and configuration settings for the remote are removed.
git remote rm <branch_name>
# rename remote repos
git remote rename old_name new_name
# filter
The useful --merged and --no-merged options can filter this list to branches that you have or have not yet merged into the branch you’re currently on.
git branch --merged
Branches on this list without the * in front of them are generally fine to delete with git branch -d;
merge
# To merge the changes made in experimental into master, run
$ git checkout experimental
(edit file)
$ git commit -a
$ git checkout master
$ git merge experimental
# If there are conflicts
git diff
conflicts 的 file 內有
<<<<<<<, =======, and >>>>>>>
# run git add on each file to mark it as resolved.
git add conflicts_file
# Once you’ve edited the files to resolve the conflicts
git commit -a
# publish your local commits
git push
checkout a file
# checkout by filename
git checkout test.py
# checkout by hash
# 查看 hash 的 code
git hist
# checkout 某個 hash
git checkout <hash>
git-rm
Usage
git rm test-file # Local
git rm -r test-folder # Remote
Opts
-n, --dry-run
-r # Allow recursive removal when a leading directory name is given.
--cached # Use this option to unstage and remove paths only from the index.
# Working tree files, whether modified or not, will be left alone.
git add
-v, --verbose
-n, --dry-run
git reset
Reset current HEAD to the specified state
# 回到 add / edit file
git reset [mode]
mode: --mixed | --soft | --hard
--mixed
Resets the index but not the working tree
(i.e., the changed files are preserved but not marked for commit) and reports what has not been updated.
$ edit
$ git add frotz.c filfre.c
$ mailx
$ git reset
$ git pull git://info.example.com/ nitfol
--soft
# Does not touch the index file or the working tree at all (but resets the head to <commit>,
# just like all modes do). This leaves all your changed files "Changes to be committed", as git status would put it.
git reset --soft HEAD~
--hard
# Resets the index and working tree. Any changes to tracked files in the working tree since <commit> are discarded.
git reset --hard HEAD~
# 還原 edit
checkout file
Tag
我們會使用 tag 功能去標記出發行版本( i.e. "V1.0" )
# 查看 repo 設定了什麼 tag
git tag
# Search tag in repo
git tag -l 'php-7.0.*'
# 加 tag
git tag v1
OR
git tag -a v1.4 -m 'my version 1.4'
# 查看某 tag 的有關資料
git show v1.4
# Checkout 某 tag
git checkout v1
OR
git checkout tags/<tag_name>
# Removing tag (再也去不了那 state)
git tag -d tag_name
# 分享標籤
# "git push" 指令並不會將標籤傳到遠端伺服器上
# "--tags" 一次過處理所有
git push origin [tagname]
To compare two tags
By Web
https://github.com/<user>/<repo>/compare/<beginning-tag>…<ending-tag>
e.g.
https://github.com/rustdesk/rustdesk-server/compare/1.1.11...1.1.12
By CLI
git diff tag1 tag2
# see only the list of files that were changed:
git diff tag1 tag2 --stat
# look at the differences for some particular file
git diff tag1 tag2 -- some/file/name
git log tag1..tag2
Undo
# Reset the Staging Area (add 了而未 commit)
git reset HEAD test.py
# undo commit
git revert HEAD
Move
git mv hello.rb lib
OR
mv hello.rb lib
git add lib/hello.rb
git rm hello.rb
.gitignore
Specifies intentionally untracked files to ignore
* git doesn't store empty folders.
* It is not possible to re-include a file if a parent directory of that file is excluded.
* working on current folder
Rules
"#" # A comment
Pattern # Each line in a gitignore file specifies a pattern.
"backup" # 略過名叫 backup 的檔案及目錄. 有隱藏的 ^Pattern$ 在首尾
(不會略過 Start_backup 及 backup_End)
"*.bak" # 所有名叫 a.bak, b.bak ... 的檔案及目錄
"_bak/" # 所有 _bak/ 目錄被略過
"/*.c" # 只略過頂層的 file.c, 不會影響 subfolder 的 file.c
"/folder/**/testfile" # matches "a/testfile", "a/x/testfile", "a/x/y/testfile" and so on
"!" # which negates the pattern
# exclude everything except directory foo/bar /* !/foo /foo/* !/foo/bar
.gitignore templates
https://github.com/github/gitignore
Remove files git ignored files from remote repository
git rm -r --cached . && \ git add . && \ git commit -m "Removing all files in .gitignore" && \ git push
Export
git clone https://gitlab.com/datahunter88/testproj.git
cd testproj
# export "master" 到 /full/path/to/zipfile.zip
# Default 是用 tar 打包, ZIP: "--format zip"
git archive --output /full/path/to/package.tar master
git archive --format zip --output /full/path/to/package.zip master
tar -tf package.tar
GUI
gitk - a tcl/tk revision tree visualizer
Element
object database
It is the rather elegant system used to store the history of your project
(files, directories, and commits.)
index file
It is a cache of the state of a directory tree, used to create commits, check out working
Apache with git
.htaccess
Create a .htaccess file in the .git folder and put the following in this file:
Order allow,deny Deny from all
.htaccess side with .git
RedirectMatch 404 /\.git <Files README.md> deny from all </Files>
Global
works for all .git directories in your site, even if there are more than one,
also hides other Git files like .gitignore and .gitmodules
# do not allow .git version control files to be issued
<Directorymatch "^/.*/\.git+/"> Order deny,allow Deny from all </Directorymatch> <Files ~ "^\.git"> Order allow,deny Deny from all </Files> <Files ~ README.md> deny from all </Files>
Cleanup - git gc
git gc
# Cleanup unnecessary files and optimize the local repository
# Housekeeping is required if there are too many loose objects or too many packs in the repository.
- compressing file revisions
- removing unreachable objects
# Some git commands may automatically run git gc
# Disable this behavior permanently
git config --global gc.auto 0
# optimize the repository at the expense of taking much more time
--aggressive
# Prune(修剪) loose objects older than date (default is 2 weeks ago)
--prune=N # Unit: day
--prune=now
Note
When git gc runs concurrently with another process,
there is a risk of it deleting an object that the other process is using but hasn’t created a reference to.
This may just cause the other process to fail or may corrupt the repository
if the other process later adds a reference to the deleted object.
Usage
du -sh .git
92M .git
git branch
v4 v5 ... v18
# 刪除不要的 local branch
# 不影響 .git 的 size
git branch -d v4
git branch -d v5
....
git gc
Counting objects: 32727, done. Delta compression using up to 2 threads. Compressing objects: 100% (16935/16935), done. Writing objects: 100% (32727/32727), done. Total 32727 (delta 17426), reused 28421 (delta 14687)
du -sh .git
85M .git
Tools
Windows GUI tool - Git SCM
Environment Variables
- GIT_AUTHOR_NAME
- GIT_AUTHOR_EMAIL
Test
# Linux
echo %GIT_AUTHOR_NAME%
# Win
echo $GIT_AUTHOR_NAME
To clear out the history of a git/github repository
# Local git
rm -rf .git git init git add . git commit -m "Initial commit"
# github git
git checkout --orphan newBranch git add -A # Add all files and commit them git commit git branch -D master # Deletes the master branch git branch -m master # Rename the current branch to master git push -f origin master # Force push master branch to github git gc --aggressive --prune=all # remove the old files
github raw download file
https://github.com/myspace-nu/jquery.fancyTable/blob/master/dist/fancyTable.min.js
的 DL Link
https://github.com/myspace-nu/jquery.fancyTable/raw/master/dist/fancyTable.min.js
PAT (Personal Access Token)
Token Format
ghp_???
建立 Token
Settings > Developer settings > Personal access tokens (classic)
https://github.com/settings/tokens
Workflow
workflow file
.github/workflows/your_file_name.yml
secrets
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-east-1
pre-written workflow by Official GitHub Actions
https://github.com/actions/checkout
...
steps:
- name: Check out code
uses: actions/checkout@v2
Doc
- http://gitimmersion.com/lab_01.html <- 做練習
- https://git-scm.com/docs/gittutorial <- 快速入門
- https://git-scm.com/docs/gittutorial-2 <-
- https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell <- Git 原理 [必看]
- https://git-scm.com/documentation <- 主要 Document