The Basics
查看git版本 **git --version**
**git init**
初始化,将文件夹变成repo,生成了.git文件夹git status
查看状态
An untracked file is one that is not under version control.我们要主动告诉git把什么文件加到仓库**git add <file>**
创建了文件的snapshot用来准备commit, 创建snapshot的过程叫staging
git add 可以添加多个文件 git add orange.html blue.html
**git commit**
将snapshot提交到 project history, 需要在编辑器中填写提交信息**git commit -m "message"**
在命令行中添加提交信息
所以保存一个项目版本分2步:
- Staging. Telling Git what files to include in the next commit.
- Committing. Recording the staged snapshot with a descriptive message.
git add不会对repo造成什么实质影响,只有git commit才把snapshot保存到repo中,成为项目的safe version
**git log**
查看Repository History**git log --oneline**
以简介的方式查看提交历史**git log --oneline <filename>...**
后面还可以添加1个或多个文件名,查看指定文件的提交历史
按q
键退出log
a new commit refers to its parentcommit
Quick Reference
git init
Create a Git repository in the current folder.git status
View the status of each file in a repository.git add <file>
Stage a file for the next commit.git commit
Commit the staged files with a descriptive message.git log
View a repository’s commit history.git config --global user.name "<name>"
Define the author name to be used in all repositories.git config --global user.email <email>
Define the author email to be used in all repositories.
Undoing Changes
View an Old Revision
每个commit记录的都是项目的历史版本
使用git log --oneline
查看历史commit信息
如果要查看id为916856d
的commit的内容,使用命令 **git checkout 916856d**
此时查看代码,会发现在 3d8d577
做的修改都消失了, 项目版本切换到了916856d
此时git log 会发现3d8d577
不见了
Return to Current Version
切换到历史本版后, 最新的版本(snapshot)去了哪里呢?
这是因为我们脱离了分支
使用命令 git checkout master
回到主分支, 就又能看到所有的commit快照了
Tag a release
给最新的版本打上标签, 这样我们就可以方便地使用标签名访问commit
git tag -a v1.0 -m "Stable version of the website"
-a 代表 annotated tag
使用命令 git tag
可以查看所有的tag
在git commit
前先 git status
查看有哪些文件要提交是个好习惯
tag就相当于对应的commit的快捷方式,如果要查看这个commit,可以用tag代替commit idgit checkout v1.0
Undo committed changes
在v1.0后我们又做了些修改,并提交为 e4dcc5b
现在要撤销这次提交,使用命令 **git revert** e4dcc5b
会发现git并没有删除e4dcc5b, 而是生成了一个新的commit 383875f, 这个commit的内容和v1.0一模一样
所以,git revert的作用是将指定的commit回退到其上一个版本(通过产生新的commit的方式)
为什么要使用get revert生成新的commit记录而不是直接移除commit记录?
在团队协作中,删除commit记录是不推荐的
接下来我们又做一些修改,添加了dummy.html文件,修改了index.html
执行命令 **git reset --hard**
, 撤销工作区和暂存区所有tracked文件的修改
发现index.html恢复成了最近一次commit的版本
git reset只作用在working directory和staging area,不会影响到committed snapshots
如果git reset不加参数,只会把staging area的文件变成unstaged
git reset —hard只能作用在tracked文件,dummy.html文件未受影响
使用命令 **git clean -f**
会删除所有untracked文件
git revert VS git reset:
The git reset command undoes changes to the working directory and the staged snapshot, while git revert undoes changes contained in committed snapshots.
Quick Reference
git checkout <commit-id>
View a previous commit.git tag -a <tag-name> -m "<description>"
Create an annotated tag pointing to the most recent commit.git checkout <tag-name>
View a previous commit.git revert <commit-id>
Undo the specified commit by applying a new commit.git reset --hard
Reset tracked files to match the most recent commit.git clean -f
Remove untracked files.git reset --hard / git clean -f
Permanently undo uncommitted changes.
Branches, Part I
Git version control由四部分组成:
- The Working Directory
- The Staged Snapshot
- Committed Snapshots
- Development Branches
In Git, a branch is an independent line of development.
View Existing Branches
查看分支: **git branch**
master是默认分支
*星号代表check out, 即工作区(working directory)显示的是这个分支的最新快照(snapshot)的内容
detached HEAD
The HEAD is Git’s internal way of indicating the snapshot that is currently checked out.
当head被detach, 我们就不能说我们在master分支上了
我的理解:
可以将HEAD和master都理解为指针, HEAD指向的快照就是当前工作区展示的内容, master指向分支最新的快照, 默认情况下HEAD和master是重合的
Create a New Branch
如果想试验一个新特性,可以先创建一个分支来写代码, 没问题了再合并到主分支
创建分支: **git branch crazy**
该命令会从当前HEAD所在节点开始创建新的分支
When git branch creates a branch, it uses the current HEAD as the starting point for the newbranch.
切换到分支:**git checkout crazy**
此时HEAD和crazy重合
在crazy分支上做些修改, 做一次commit, 则可以看到分叉 fork
git log 只会显示当前分支上的提交历史
从分支头部回溯到第一次提交都属于这个分支
Rename the rainbow
将crazy.html重命名为rainbow.html**git rm crazy.html**
告诉git不再track crazy.html, 同时删除工作区的文件
git 很聪明地知道我们重命名了文件
Merge branch
假如当前分支如上图所示
先切换到master分支: git checkout master
将css分支合并到master分支: **git merge css**
因为master是css的祖先, 所以git只是简单地把master移到了和css相同的位置, 这叫做 fast-forward merge
此时master和css拥有一模一样的提交历史
删掉css分支: **git branch -d css**
Quick Reference
git branch
List all branches.git branch <branch-name>
Create a new branch using the current working directory as its base.git checkout <branch-name>
Make the working directory and the HEAD match the specified branch.git merge <branch-name>
Merge a branch into the checked-out branch.git branch -d <branch-name>
Delete a branch.git rm <file>
Remove a file from the working directory (if applicable) and stop tracking the file.
Branches, Part II
master是stable branch, 其他分支可以称为topic branches
- Create a new branch for each major addition to your project.
- Don’t create a branch if you can’t give it a specific name.
用merge合并分叉的2个分支,会产生一个新的commit, 这叫做 3-way merge
git checkout crazy
git merge master
此时,crazy既能访问自己的历史节点,也能访问master的历史节点
再对文件做一些修改,使用如下命令:**git commit -a -m "Add CSS stylesheet to rainbow.html"**
这个命令将git add和git commit -m合并了,-a表示将所有tracked文件添加到staging area
Stage all tracked files and commit the snapshot using the specified message.
当git merge产生冲突时
修改冲突的文件, git add 修改的文件
git commit不需要加-m, 因为git会自动生成merge信息
删除crazy和crazy-alt分支
删除未合并的分支要用 **git branch -D <branchname>**
Rebasing
用git merge合并分支, commit历史会变得很凌乱
Git提供了git rebase移动分支,改变其base(父节点)
新建一个文件夹about, 新建文件index.html
git add 可以添加文件夹
git add about
git commit -m "Add about section"
用于紧急更新的分支可以叫hotfix分支
当前分支如上图所示,执行命令:**git checkout about**
**git rebase master**
意思是把about的base(基)改为master最前方
结果变成下图所示:
about分支的2次提交移动到了master的前面
git add还可以加路径, 例如: **git add about/me.html**
rebasing interactively
git rebase not only lets youmove branches around, it enables you to manipulate individual commits as you do so.
加入参数 -i
git rebase -i master
可以调整顺序, 合并(squash) commit等等
git rebase会生成新的commit id
if you were to delete a line from the rebase listing, the associated commit wouldn’t be transferred to the new base, and its content would be lost forever.
Stop to Amend a Commit
**git rebase -i master**
将pick改为edit, 当git处理到这个commit时,会停下来让我们修改
对文件做出修改后
git add about/mary.html
git status
git commit --amend
—amend是使用当前的staged commit替换掉旧的commit
此时我们仍然停在这个commit, 后面还有commit要处理,使用命令 **git rebase --continue**
继续
将about分支合并到master
因为master是about的base
所以可以直接用fast-forward merge
git checkout master
git merge about
git branch -d about
这里用**git rebase about**
也是一样的效果
Quick Reference
**git rebase <new-base>**
Move the current branch’s commits to the tip of
or a commit ID.**git rebase -i <new-base>**
Perform an interactive rebase and select actions for each commit.**git commit --amend**
Add staged changes to the most recent commit instead of creating a new one.**git rebase --continue**
Continue a rebase after amending a commit.**git rebase --abort**
Abandon the current interactive rebase and return the repository to its former state.**git merge --no-ff <branch-name>**
Force a merge commit even if Git could do a fast-forward merge.
Rewriting History
**git checkout -b new-pages**
创建并切换到new-pages分支
commit的原则:
- Commit a snapshot for each significant addition to your project.
- Don’t commit a snapshot if you can’t come up with a single, specific message for it.
**git rebase -i master**
**git reset --mixed HEAD~1**
撤销当前commit, 但工作区内容保持不变
接连做2次修改和commit
git add red.html index.html
git status
git commit -m "Add red page"
git add yellow.html index.html
git status
git commit -m "Add yellow page"
git rebase --continue
成功地删除了Add new HTML pages这个commit, 添加了2个新的commit
Remove the Last Commit
**git reset --hard HEAD~1**
撤销当前commit, 工作区内容也恢复成上一个commit
不加参数—hard, 默认为—mixed, 工作区内容不会改变
实际上是将分支指针移动到了HEAD~1, 之后的commit就不可见了
git 用 reflog记录每次你对仓库的更改
使用命令 **git reflog**
查看
按空格键查看完整记录, 按q退出
Revive the Lost Commit
**git checkout 002926a**
将HEAD移动到被撤销的commit**git checkout -b green-page**
创建一个新的分支
Filter the Log History
查看2个分支的不同,使用 log-filtering语法**git log new-pages..green-page**
这个命令会列出在green-page分支不在new-pages分支的commits
还可以用这个命令指定git log输出的条数**git log HEAD~4..HEAD**
**git log HEAD~4..HEAD --oneline**
为此,Git提供了更简单的命令:**git log -n 4**
**git log -n 4 --oneline**
Merge in the Revived Branch
git checkout master
git log HEAD..green-page --stat
因为此时HEAD移动到master了, 所以等价于git log master..green-page --stat
—stat表示显示commit的详细更改
将master与green-page合并(fast-forward merge)git merge green-page
或git rebase green-page
删除2个分支git branch -d new-pages
git branch -d green-page
It’s important to realize that Git uses the tip of a branch to represent the entire branch. That is to say, a branch is actually a pointer to a single commit—not a container for a series of commits.
The history is represented by the parent of each commit (designated by arrows), not the branchitself. So, to request a new branch, all Git has to do is create a reference to the current commit.
And, to add a snapshot to a branch, it just has to move the branch reference to the new commit.
Quick Reference
git reflog
Display the local, chronological history of a repository.git reset --mixed HEAD~<n>
Move the HEAD backward git reset --hard HEAD~<n>
Move the HEAD backward git log <since>..<until>
Display the commits reachable from
either commit ID’s or branch names.git log --stat
Include extra information about altered files in the log output.