基本概念
- 工作区:能看到的目录
- 暂存区:stage 或 index。一般存放在 .git/index 中,所以把暂存区有时也叫作索引(index)。
- 版本库:工作区有一个隐藏目录 .git 就是 Git 的版本库。
文件入库流程:
图中左侧为工作区,右侧为版本库。"index" 为是暂存区(stage/index), "master" 是 master 分支所代表的目录树。
图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
当对工作区修改(或新增)的文件执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
当执行 git reset HEAD 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
当执行 git rm --cached <file> 命令时,会直接从暂存区删除文件,工作区则不做出改变。
当执行 git checkout . 或者 git checkout -- <file> 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
当执行 git checkout HEAD . 或者 git checkout HEAD <file> 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
1. 创建版本库
1.1 git init 初始化仓库
$ git init
Initialized empty Git repository in G:/learngit/.git/
1.2 git add 跟踪文件
git add . 跟踪所有改动过的文件
git add <file> 跟踪指定文件
$ git add README.md
1.3 git commit 提交到仓库
$ git commit -m "wrote a readme file"
[master (root-commit) 8438389] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 README.md
1.4 git status 查看git 状态
$ git status
On branch master
nothing to commit, working directory clean
2. 版本管理
2.1 git diff 查看修改内容
$ git diff README.md
diff --git a/README.md b/README.md
index d8036c1..013b5bc 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
\ No newline at end of file
2.2 git reset 回退到上一版本
$ git reset --hard HEAD^
HEAD is now at 8438389 wrote a readme file
在Git中,用 HEAD
表示当前版本,上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
2.3 回到回退之前版本
Git 提供了一个命令 git reflog
用来记录你的每一次命令。
$ git reflog
8438389 HEAD@{0}: reset: moving to HEAD^
43597ec HEAD@{1}: commit: add distributed
8438389 HEAD@{2}: commit (initial): wrote a readme file
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (master)
$ git reset --hard 43597ec
HEAD is now at 43597ec add distributed
2.4 撤销工作区修改
命令:git checkout -- file
作用:撤销工作区的全部修改,这里有两种情况:
一种是readme.txt
自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt
已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit
或git add
时的状态。
2.5 撤销暂存区修改
命令:git reset HEAD <file>
作用:把暂存区的修改回退到工作区。HEAD
表示最新的版本。
$ git reset HEAD README.md
Unstaged changes after reset:
M README.md
2.6 删除文件
先手动删除文件,然后使用 git add<file> 的效果和 git rm <file> 是一样的。
$ git rm test.txt
rm 'test.txt'
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (master)
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: test.txt
3. 远程仓库
3.1 添加远程仓库
命令:git remote add origin <URL>
$ git remote add origin git@github.com:Zhangtao153/learngit.git
3.2 推送本地库内容到远程库
命令:git push origin <branch-name>
$ git push -u origin master
Warning: Permanently added the RSA host key for IP address '192.30.255.112' to the list of known hosts.
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (10/10), 855 bytes | 0 bytes/s, done.
Total 10 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To git@github.com:Zhangtao153/learngit.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
当前分支 master
推送到远程
3.3 查看远程仓库
git remote -v
$ git remote
origin
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (dev)
$ git remote -v
origin git@github.com:Zhangtao153/learngit.git (fetch)
origin git@github.com:Zhangtao153/learngit.git (push)
$ git remote show
origin
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (master)
$ git remote show origin
* remote origin
Fetch URL: git@github.com:Zhangtao153/learngit.git
Push URL: git@github.com:Zhangtao153/learngit.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.4 从远程库克隆
git clone <url>
$ git clone git@github.com:Zhangtao153/learngit.git
Cloning into 'learngit'...
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 10 (delta 1), reused 10 (delta 1), pack-reused 0
Receiving objects: 100% (10/10), done.
Resolving deltas: 100% (1/1), done.
Checking connectivity... done.
3.5 本地创建和远程分支对应的分支
从远程clone的代码库默认只有master分支。
命令:git checkout -b dev origin/dev
$ git checkout -b dev origin/dev
Switched to a new branch 'dev'
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
3.6 修改远程仓库
方法一:
git remote set-url origin <url>
git remote rm origin
git remote add origin [url]
4. 分支管理
4.1 创建切换分支
命令:git checkout -b dev 或 git switch -c dev
作用:创建并切换分支
git checkout
命令加上-b
参数表示创建并切换,相当于以下两条命令:$ git branch dev
$ git checkout dev
$ git checkout -b dev
Switched to a new branch 'dev'
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (dev)
$ git branch
* dev
master
4.2 合并分支
命令:git merge <branch>
作用:合并指定分支到当前分支
$ git merge dev
Updating 35bc9a6..83ef1fc
Fast-forward
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
Fast-forward
“快进模式”,就是直接把master
指向dev
的当前提交,所以合并速度非常快。
通常合并分支时,如果可能,Git会用
Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用
Fast forward
模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
$ git merge --no-ff -m "merge with no-ff" zth
Merge made by the 'recursive' strategy.
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (master)
$ git log --graph --pretty=oneline --abbrev-commit
* c5df1ca (HEAD -> master) merge with no-ff
|\
| * 5db3e3d (zth) delete merge
|/
* 6707c86 add merge
* 7e760b4 add on zth branch
* 650cdbc clear on master
4.3 删除分支
命令:git branch -d <branch>
$ git branch -d dev
Deleted branch dev (was 83ef1fc).
4.4 查看分支合并情况
命令:git log --graph --pretty=oneline --abbrev-commit
或:git log --graph --oneline
$ git log --graph --pretty=oneline --abbrev-commit
* 8e7b6c4 conflict fixed
|\
| * e920442 update on dev
* | e15ba0e update on master
|/
* 83ef1fc add on dev
* 35bc9a6 delete test.txt
* fd68a6a add file test.txt
* a8d2e0d 手动删除
* 1d243ca add test file
* 8438389 wrote a readme file
4.5 保存现场
在创建一个新的分支用来修改 bug 时,当前分支的工作还没提交,可以通过 stash
功能把当前工作现场“储藏”起来,等以后恢复现场后继续工作。
原因:所有分支共享工作区和暂存区
$ git stash
Saved working directory and index state WIP on issue-004: c5df1ca merge with no-ff
git stash list
$ git stash list
stash@{0}: WIP on issue-004: c5df1ca merge with no-ff
stash@{1}: WIP on dev: c5df1ca merge with no-ff
恢复现场方法:
一: git stash apply
恢复,但是恢复后,stash内容并不删除,需要用git stash drop
来删除;
二: git stash pop
,恢复的同时把stash内容也删了:
$ git stash pop
On branch issue-004
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (020a507cf2c1cd55460d17081db6671b7e075ed6)
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (issue-004)
$ git stash list
stash@{0}: WIP on dev: c5df1ca merge with no-ff
$ git stash apply stash@{0}
4.6 git cherry-pick
作用:合并不同分支的若干个 commit 到当前分支
语法:
git cherry-pick <C commit-id> <D commit-id> <E commit-id>
5. 多人协作工作模式
-
首先,可以试图用
git push origin <branch-name>
推送自己的修改; -
如果推送失败,则因为远程分支比你的本地更新,需要先用
git pull
试图合并; -
如果合并有冲突,则解决冲突,并在本地提交;
-
没有冲突或者解决掉冲突后,再用
git push origin <branch-name>
推送就能成功!
如果 git pull
提示 no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令 git branch --set-upstream-to <branch-name> origin/<branch-name>
。
6. 标签管理
6.1 创建标签
命令:git tag <name> [commit]
-a
指定标签名,-m
指定说明文字
首先选择分支,默认在最新提交的 commit 上。
$ git tag v1.0
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (dev)
$ git tag v0.9 add2dbd
6.2 查看所有标签
git tag
$ git tag
v0.9
v1.0
6.3 查看标签信息
git show <tagname>
$ git tag -a v0.8 -m "version 0.8 release" 94b83a0
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (dev)
$ git show v0.8
tag v0.8
Tagger: Zhangtao153 <13289265979@163.com>
Date: Wed Oct 21 23:51:54 2020 +0800
version 0.8 release
commit 94b83a06c04b8b3a5ca5af4443dda614bc3b1441 (tag: v0.8)
Author: Zhangtao153 <13289265979@163.com>
Date: Wed Oct 21 21:32:49 2020 +0800
commit on issue-005
diff --git a/README.md b/README.md
index 25ed040..af0e009 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,2 @@
Git is a version control system.
-Git is free software.哈哈zth delete and update
+Git is free software.哈哈zth delete and update on issue-005
6.4 删除标签
删除本地标签:
git tag -d <tagname>
$ git tag -d v0.9
Deleted tag 'v0.9' (was add2dbd)
删除远程标签(先删除本地,再删除远程):
$ git tag -d v0.8
Deleted tag 'v0.8' (was 120a8d2)
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (dev)
$ git push origin :refs/tags/v0.8
To github.com:Zhangtao153/learngit.git
- [deleted] v0.8
6.5 推送标签到远程
推送指定标签:
git push origin <tagname>
推送全部尚未推送到远程的本地标签:
git push origin --tags
$ git push origin v1.0
Enumerating objects: 28, done.
Counting objects: 100% (28/28), done.
Delta compression using up to 4 threads
Compressing objects: 100% (18/18), done.
Writing objects: 100% (26/26), 1.95 KiB | 667.00 KiB/s, done.
Total 26 (delta 12), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (12/12), done.
To github.com:Zhangtao153/learngit.git
* [new tag] v1.0 -> v1.0
Administrator@WIN-DTNF3GRDH5R MINGW64 /g/learngit (dev)
$ git push origin --tags
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 167 bytes | 167.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:Zhangtao153/learngit.git
* [new tag] v0.8 -> v0.8