禁止转载
<< proGit >>
脑图 1: chapter1 Get start
1.1 Local: keep patchs = start + 每个文件 每次变动 的 patch (碎片) / 差异 = 任一时刻 的 files
/
| 解决 的 问题: `开发者` 间在 `不同系统` 间 `协作`
/
1. VCS 版本控制系统 |—— 1.2 中心化的
/ \
| | 缺点: 中心瘫痪 => 系统瘫痪 => 若没备份好 => 丢失整个 history
\
| 1.3 分布式: 客户 check out files 的 最近一次快照 + 镜像 出 仓库 含 整个 history
=> 每个 clone 都是 完整备份
Get start ——|
| 2.1 Snapshots( 快照 ), Not Differences
/
| | commit 时, 给 所有 files 拍 快照, store 快照的 refenence
|
| |—— 2.2 Operation 几乎 都在 Local
|
| | local ( database ) 含 project 的 整个 history
\ |
2. Git 5大特点 |—— 2.3 Integrity ( 完整性 )
|
| store 前, hash 校验 文件内容 ( 算出 hash值 ) 与 文件路径 相应 hash 值 => 可 检测出 文件 是否 败坏
|
|—— 2.4 通常 只 Adds Data
| 撤销 ( undo )
| => commit a snapshot 后, 可 恢复 似乎 丢失的 data
|
| modified = changed + haven't commited to database
| /
\
2.5 file 主要处于 3 种 state — staged = marked modified file to go into next commit snapshot
\
committed = data is safely stored in local database
working tree
/
=> 导致 git project 3 个主要 section - staging area / index
\
Git directory
脑图 2: chapter2 Git basics
cd projectDir
/ git init
local directory -> turn into (转变为) -> Git repo
/ \ git add
/ git commit
/
1. Get a Git repo
\
/ clone Git repo from elsewhere: git clone <url>
|
in the `last ( 最近一次 ) snapshot` = `unmodified`
| /
tracked files — `modified + not staged`
| \
`newly ( 最新 ) staged` = `modified + staged`
| /
/
|—— 2. tracked / untracked files: tracked files = files that `Git knows about`
\
| \
untracked files: else = dir 中 new file (不是指 working dir 中 ) + repo 外 ( 不算在 working dir 中 )
|
3.1 check file status: git status
| /
|—— 3.2 Track New Files : git add
| |
|—— 3.3 Stage Modified Files: `tracked file -> change -> status modified -> git add : 以 stage modified files -> 若 再次 change -> 需再次 git add`
| |
|
| | compares `working directory with staging area`
| /
| | git diff
| / \
| | / 结果是 changes that haven't staged
|—— 3.4 查 Staged / Unstaged Changes
| | \
| \
|—— 3. Record Changes ——| git diff --staged => changes staged
to Repo |
| |—— 3.5 staging area -> local repo: git commit
|
| | 自动 stage commit 前 已 tracked 的 files
| /
| |—— 3.6 skipping staging area: git commit -a 选项
| \
| | git commit -a -m "comment" = git add modifiedButNotStagedFile + git commit -m "comment"
|
| |
| rm + git rm + git commit
| \ /
3.7 Remove files
| \
git rm --cached: 保持在 hard drive, 但 让 Git 不再 track it
Git basics —|
git log // 只 显示 所在 (check out) 分支 的 commit history
| /
|— git log -p 2
|—— 4. 查 history
+ changes between commits —|
|
|— git log --oneline --decorate // 查 branch pointer 指向 哪
| \
git log --oneline --decorate --graph --all
|
scenario: commit -> forgot to stage change you want to add to this commit
| /
|
| step1: git commit -m 'Initial commit'
| /
|
5.1 --amemd | —— solution — step2: git add <forgotten_file>
| /
| | \
| step3: git commit --amend
| |
|
| | old commit 不记录在 history
| \ /
| 2 点注意
| \
| 只应该 amend 仍在 local 而未被 push 的 commit
|—— 5. undo things
undo mistakes —— |
|
| scenario: changed 2 files + 想 单独进行 2 次 commit
| -> 但 不小心 用 git add * 将 2 changes 均 stage
| / -> 如何 unstage one of the staged file ?
|
|—— 5.2 work with staging area : unstage a staged file
| git status 的 hint: use "git reset HEAD <file>..." to unstage
| \ / use "git restore --staged <file>..." to unstage (Git 2.23.0)
| solution
| \
| git reset HEAD <stagedFile>
| git restore --staged <stagedFile> (Git 2.23.0)
|
|
| scenario: 不想保存 modified (but hven't staged) change
\ /
| 5.3 work with working directory : unmodify a modified file git status 的 hint: use "git checkout -- <file>..." to discard changes in working directory
\ / use "git restore <file>..." to discard changes in working directory (Git 2.23.0)
| solution
\
| git checkout -- <unwantedChangedFile>
git restore <unwantedChangedFile> (Git 2.23.0)
|
6.1 remote 含义: repo 在 其他地方 (local elsewhere 或 network / Internet 上 )
| /
git clone <remote_url>
| | / cd localWorkingDirectory
| git remote // hint: 至少 1 个 origin: Git 给出的 你所 clone 的 `server 的 default name`
| |—— 6.2 show Remotes: git remote|
| git remote -v // read 和 write 的 URLs
| | |
\ \ git remote show <remote> / git remote show origin ( show more info about remote )
6. Work with Remotes |
git fetch <remote> : 得 该 remote 下 所有 branches 的 references
| /
git fetch: 必须基于 已有 git repository |
| 比如, git clone -> git fetch |— git fetch origin : dowmload 名为 origin 下 的 repo
/ |
| / \
git fetch : 只 dowmload 到 local repo + not mrege it into loacl current branch
|—— 6.3 fetch & pull
\
| \
git pull = git fetch + `merge` that remote branch `into` current branch
|
git push <remote> <branch> : git push origin master // push master branch to origin server
/
|—— 6.4 push
\
| you and others: clone -> others push -> you 应 fetch + incorporate into ( merge )
\
Rename / Remove Remotes git remote rename / git remote remove
脑图 3: chapter3 Git Branching
前 40 character 是 ( 该 branch 所 `指向` 的 ) 相应 commit 的 SHA-1 校验和: 40 个 字符 (十六进制数)
/
本质 上: 是 1 个 file, 含 41 个 character
/ \
/ + 1 character: newline ( 换行符 )
1.0 branch 是什么? 2 种理解
/ \
/ \
| 形象 上: 是 1 个 `可移动的 pointer : 指向 相应 commit`
| master: Git 中 default branch
|
snapshot 是什么 ? `某次 commit 相应的 version`
| Git stores snapshots
checksum -> checksum 放 staging area
|——1.1 stage: 对 每个 file /
\
| store 为 `blob object: 表示 file 内容`
|
checksum
| /
对 每个 subdirectory
| / \
/ store 为 `tree object: 列出 ( list ) 该 directory 内容`, 即 `每个 file name` 及 对应存储的 `blob` 信息
|——1.2 commit
\ metadata ( 元数据 ) : author's name / email addr
| \ /
\ /
| store a `commit object`, contain — a pointer to 工程的 root tree (content staged) -> 用以在需要时 `重建 snapshot`
\
| \ 0 parent : initial commit
\ /
| pointers to directly parent(s) commit — 1 parent : normal commit
\
| n parents: 来自于 多分支 合并 的 commit
| commit -> change -> commit : commit 存 a pointer to 它最前面一次的 commit
1. Branches in a Nutshell ——|
/
/ | git branch <branchName> // 创建 pointer 指向 当前所在 commit, 只创建 不切换
| /
|—— 1.3 create branch
| \
| Git 如何知道当前所在分支 ?
| 用 HEAD : a pointer 指向 当前所在 local branch
|
|
| 1) 将 HEAD 移到 已有分支
| /
| git checkout <branchName> 切换到 已有分支
| / \
| / 2) revert (还原) working directory 中 files 为 该 branch 上 last commit 时的 snapshot
| \ /
1.4 Switch Branch
| \
\
\
| git checkout -b <newbranchname> 创建分支 的同时 切换过去
= git branch <newbranchname> + git checkout <newbranchname>
|
| scenario: master 分支 -> `切出去` -> change & commit -> `切回来` -> change & commit -> divergent ( `分支 分离` )
|
| (1) 欲解决问题 53: issue-tracking system
/ => 新建并切换到 iss53 branch -> change -> git commit -a -m
| |
git checkout -b iss53
| | vim file + git commit -a -m '*** [issue 53]'
| |—— (2) src 分支 ( master ) 上 有 issue 要 fix
切到 master 分支 -> 新建 并 切到 fixBranch
| | -> change -> git commit -a -m
-> test ok -> 切回 master 分支 -> 将 fixBranch 合并回 (merge back into) master 分支
| | -> 删 fixBranch (不再需要)
note: 将 branch1 合并到 branch2: 先切到 branch2 -> git merge branch1
| |
git checkout master
| | git checkout -b <hotfix>
| | vim index.html + git commit -a -m "..."
2.1 Basic
| Branch—| test ok
/
| | | git checkout master
git merge <hotfix>
| | |
git branch -d <hotfix>
| | |
fast-forward(快进) merge: commit1OnMaster 是 commit2OnFixBrach 的 直接前驱
| | | => merge 只需移动 master pointer, 没有 divergent work 要 merge
\
| | (3) 切回 iss53 branch 继续工作
git checkout iss53
| | vim + git commit -a -m "..."
| |
|—— 2. Basic Branch—|— 2.2 Basic — (4) iss53 完成 -> 合并回 master -> delete iss53Branch
& Merge Merge
| | git check master
git merge iss53
| | git branch -d iss53
| | divergent merge: three-way merge
snapshot to merge into
| | snapshot to merge in
common ancestor
| | => 新建 commit 指向 新建 snapshot
| |
(1) user2 和 user2 改 同一文件 同一(part)行:
| | / user1 & user2 clone -> user1 push -> user2 push: Merge confict
\ |
| 2.3 Basic
Merge |
| Conflicts
|— (2) branch1 和 branch2 改 同一文件 同一(part)行:
| branch1 commit -> branch2 commit: Merge conflict
|
| \ solution: merge conflict -> 手动打开冲突文件, <<<<<<< ======= >>>>>>> 3行删掉, 其余改成想要 成为的样子
======= 前面是 HEAD 分支 / 当前 user 的 push, 后面是 被合并分支 / 另一 user 的 push
Git Branching ——|
| git branch // 查 当前所有分支, * 表示 当前所在分支, 即 HEAD 所指分支
/
|—— 3. Branch Management — git branch -v // 查 每个分支上 the last commit
\
| change branch name // 略
| 并行分支 / silo (发射井)
/
long-running branches
| \
/ 稳定性分级: 到达 更高稳定级 时, 合并到 更高稳定级的 branch
|—— 4. Branching Workflows
\
| Topic Branches: 每个 主题/问题 用一个分支
| 在 Git 本地仓库, 没有与 server 交互
| 书签 作用: 表示 最近一次 与 remote repo 交互 时, remote branch 的 位置
/
| |—— 是 remote branches 状态的 reference
| |—— 是 local reference => 你不能 move 它, 与 server 交互时, Git move 它
| / 5.1 Remote-tracking branches —— |—— 名字: <remote>/<branch> 如 origin/master
|
| | 找到 origin 表示的 server: 如 git.ourcompany.com
| /
| |—— 与 remote 同步: git fetch <remote> 如 git fetch origin — fetch 本地没有的 data, not modify working directory
| \
| | 移动 origin/master pointer 到 remote 最新 commit 在 local 的 commit
| \
| fetch 后, 想 merge 到 current branch: git merge origin/currentBrachName
|
| push local 分支 branch 到 remote 分支 branch
| git push <remote> <branch> // <=>
| git push <remote> <branch:branch> // <=> Git 自动扩展
| / git push <remote> <refs/heads/branch:refs/heads/branch>
| /
|—— 5.2 push — refs/heads/
| \
\ push local 分支 branch1 到 remote 分支 branch2
| | git push <remote> <branch1:branch2>
| | (1)是 与 remote branch 有 直接关系 的 local branch
/
|—— 5. Remote Branches | | (2) clone => 自动创建 master 分支 以 track origin/master( remote master 分支 from origin )
| |—— 5.3 tracking branches |
(3) 新建 tracking branch:
| | | git checkout -b <branch> <remote>/<branch> // local branch 可以 和 remote branch 不同
| | | git checkout --track origin/branch1 // <=>
= git checkout -b branch1 origin/branch1
| | \
(4) 将 已有 local branch 设为 track remote branch (upstream branch):
| | git checkout localBranch
git checkout --track origin/remoteBranch
|
|—— 5.4 pull: git pull = git fetch + git mrege remoteBranchThatCurrentLocalBranchTracking
|
|
| \ 5.5 delete remote branch: git push <remote> --delete <remoteBranch>
| merge
/
| 6.1 将 change 从 1 个 branch 包含进 另一 branch
/ \
| | rebase
\
6. Rebase — |—— 6.2 四步
| git checkout branch1
git rebase master
| git checkout master
git merge branch1
|
|—— 6.3 弊端: 会改变 commit history => 关注 commit history 时, 不要 rebase
| rebase local changes before push
\ /
6.4 最佳实践
\
never rebase that you have pushed somewhere
脑图4 Git Internals: Git 的 内部实现
内容寻址 文件系统
/
0. Git
/ \ key: 哈希值
| /
key -value 数据存储
| \
value: content
| Plumbing 命令: UNIX 风格, 从 脚本 调用
|—— 1. Plumbing( 管道 / 底层 ) /
& Porcelain (陶瓷/UI 用户友好)
命令 objects 目录: 存 database 的 内容
| /
|—— refs 目录 : 存 pointers to commit objects
| \
.git目录|
|
|—— HEAD 文件 : point to 当前所 check out 的 branch
| \
index : staging area
|—— 2. Git Objects
|—— 3. Git References: git remote add origin git@github.com:mytest.git
git push origin master
|
(1) remote branch 与 local reference 的 映射 的 更复杂的控制
/
| | (2) git remote add origin https://github.com/schacon/simplegit-progit
fetch = +refs/heads/*:refs/remotes/origin/* // <src>:<dst>
| | fetch all references under refs/heads (remotely), writes to refs/remotes/origin/ locally
Git Internals | | (3) pull: master branch (remotely) -> origin/mymaster (locally)
git fetch origin master:refs/remotes/origin/mymaster
|—— 4. refspec |
\ (4) push: master branch (locally) -> qa/master (remotely)
| git push origin master:refs/heads/qa/master
|—— 5. Transfer Protocols: http / ssh
\
6. Data Recovery: git log -g // 查 HEAD@{1} commitId
git branch <recover-branch> <HEAD1CommitId>
1 开始 Git
1.1 Version control
是 1个 `system`,
`记录` 着 各 `文件 ( 如 source code ) 随时间的 changes`,
使得 `以后` 可以 `召回` 特定版本
Version Control System (VCS)
也可以用于 `image`
image.png
image.png
image.png
1.2 Git 历史
Linus 为了 方便管理 Linux 源码
1.3 what's Git
`理解本节`, 就能 `理解 Git 工作原理 + 易 高效运用 Git`
1. Snapshots( 快照 ), Not Differences
`(1) 基于差异` 的 VCS
image.png
(2) Git
image.png
2. Operation 几乎 都在 Local
`offline => commit 到 local repo -> 等 onlie => commit 到 remote repo`
3. Integrity ( 完整性 )
文件内容
-> 计算 SHA-1 hash 值 ( 40 位 16进制值 )`
-> 作 文件路径
-> `transmit 或 经历一段时间`
-> `校验` 文件`内容 ( 算出 hash值 )` 与 `文件路径 相应 hash 值`
-> `相符 才 store` / 不符 => `Git 检测出 文件 败坏`
4. 通常 只 Adds Data
5. 3 个 state & 3 个主要 section
image.png
1.4 命令行
可运行所有 Git 命令
GUI 只实现 部分
1.5 安装 Git
image.png image.png1.6 Git 环境配置
git config
1. 查 settings (刚安装时为 空) 以及 来自哪里
git config --list --show-origin
2. 查 settings
git config --list
3. 配置 Identity
git config --global user.name "liyu"
git config --global user.email liyu030076@163.com
image.png
1.7 help
git help <verb>
git help config
2 Git 基础
Repository: repo 仓库
本章包含了 `所有 基础命令`, 足以 完成 Git 常用功能
2.1 Get a Repo
2 种方法:
1. turn local dir into git repo
(1) initialize repo
$ cd projectDir
$ git init
creates 子目录 .git ( contains all repo files )
nothing tracked
Ubuntu:
git init.png
Windows:
image.png
(2) track files + commit
git add: 指定要 track 的 files
git commit
$ git add file1.c
$ git add subDir1/file2.c
$ git commit -m "Initial project version"
image.png
2. clone Git repo
Git 的 传输协议:
(1) https 协议
https://
(2) SSH 协议
git://
user@server:path/to/repo.git
$ git clone https://github.com/libgit2/libgit2
// 更名
$ git clone https://github.com/libgit2/libgit2 mylibgit
2.2 Record Changes
到 Repo
clone = all files tracked + unmodified
working dir
中 每个 file 2 state: tracked / untracked
1. check file status
git status
(1) Init Git repo / clone repo -> status
clone repo status.png
working directory clean == none of tracked files modified
(2) project 中 新增 file => untracked
stop tracking files
stage / commit changes
2. Track New Files
git add
$ git add README
$ git status
image.png
3. Stage Modified Files
tracked file -> change -> status modified -> git add : 以 stage modified files -> 若 再次 change -> 需再次 git add
4. 查看 Staged 和 Unstaged Changes
想准确知道 what you changed
git diff
2点
(1) changed + not staged
(2) staged + not commit
image.png
5. commit change
git commit
6. skip staging area: git commit -a
7. Remove file
2.3 查 Commit History
查 history + changes between commits
git log
git log -p 2
`-p`: shows difference (the `patch` output) introduced in each commit`
2.4 撤销 ( Undo
) Things
undo mistakes
1. --amend 选项
在 first_commit 上 添加 forgotten_changes
$ git commit -m 'Initial commit'
$ git add forgotten_file
$ git commit --amend
2点注意:
(1) old commit 不记录在 history
不是 将 old_commit push 之后 再 进行 new commit,
而是 好像 old commit 从没发生
(2) 只应该 amend 仍在 local 而未被 push 的 commit
2. work with staging area: unstage a staged file staging area
3. work with working directory: unmodify a modified file
2.5 Work with Remotes
collaborate (协作)
Remote repositories can be on your local machine
remote 含义: 不是指 repo 必须在 network 或 Internet 上, 而是指 repo 在 其他地方
$ git fetch https://gitee.com/liyu_mypassion/first_remote_repo.git
fatal: not a git repository (or any of the parent directories): .git
$ git clone https://gitee.com/liyu_mypassion/first_remote_repo.git
Cloning into 'first_remote_repo'...
remote: Enumerating objects: 12, done.
remote: Counting objects: 100% (12/12), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 12 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (12/12), 2.25 KiB | 461.00 KiB/s, done
$ cd first_remote_repo
$ git remote
origin
$ git remote -v
origin https://gitee.com/liyu_mypassion/first_remote_repo.git (fetch)
origin https://gitee.com/liyu_mypassion/first_remote_repo.git (push)
$ git remote show origin
* remote origin
Fetch URL: https://gitee.com/liyu_mypassion/first_remote_repo.git
Push URL: https://gitee.com/liyu_mypassion/first_remote_repo.git
HEAD branch: master
Remote branch:
master tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
3 Git Branching
Git’s killer ( 杀手锏 ) feature
3.1 Branches in a Nutshell
例: dir 含 3 files
git add README test.rb LICENSE
git commit -m 'Initial commit'
image.png
image.png
(1) create branch
image.png image.png image.png(2) switch branch
master 分支 -> 切出去
-> change & commit -> 切回来
-> change & commit -> divergent ( 分支 分离
)
3.2 Basic Branch & merge
(1) Basic branch
image.png image.png image.png image.png image.png image.png(2) Basic merge
divergent merge: three-way merge
(3) Basic Merge Conflicts
1. user2 和 user2 改 同一文件 同一行: user1 push -> user2 push: Merge confict
2. branch1 和 branch2 改 同一文件 同一行: branch1 commit -> branch2 commit: Merge conflict
3.3 Branch Management
git branch
git branch -v
3.4 Branching Workflows
1. long-running branch
2. Topic Branches
每个 主题/问题 用一个分支
3.5 Remote Branches
(1) Remote-tracking branches
image.png image.pngimage.png
网友评论