三种状态
你的文件可能处于处于三种状态之一:已提交(committed)、已修改(modified)和已暂存(staged)
由此引入 Git 项目的三个工作区域的概念:Git 仓库、工作目录以、暂存区域。
基本的 Git 工作流程如下:
在工作目录中修改文件。
暂存文件,将文件的快照放入暂存区域。
提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
用户信息
安装完git,第一件事就是设置用户名和邮件地址,这些信息会在每次提交时使用
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
git config --list 可以查看你的 git 配置信息
$ git config --list
初始化 Git 仓库
在当前目录下初始化仓库
git init
这个命令会将本目录初始化为一个代码仓库,并在目录中增加 .git 目录,里面是关于本仓库的所有信息。
初始化之后,目录中的文件并没有加入到 git 的版本控制中,需要手动将文件添加到 git 的控制列表中,操作见下一步。
$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version
查看当前状态
git status
查看当前目录下的文件状态,如果有文件未加入到跟踪中,会提示你。
git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
?? 表示未跟踪的文件
A 表示新添加的文件
MM 右边的M表示修改后未保存到暂存区,左边表示修改并放入了暂存区
添加文件
如果我们新建了一个名为 README 的文件,git status 会显示文件没有被跟踪,通过以下指令把文件添加到 git 的文件跟踪中。
加入到跟踪中后,没有 commit 之前,文件处于暂存区。
git add README
如果这时候修改了 README 文件,再用 git status 查看状态的时候,会看到提示 changes not staged for commit,此时如果想在下次 commit 的时候提交这次修改,需要再次 git add 这个文件。
git add 可以理解为标记文件到下次提交,而非只是添加文件到跟踪状态
查看区别
在修改了文件之后,没有添加到暂存区之前,可以用 git diff 查看前后版本的区别
这是在文件没有添加到暂存区的时候的查看方式,在存入后,需要用 git diff --cached 来查看不同
提交文件
在命令中输入此次提交的信息,多个 -m 参数会作为多个分段。
git commit -m '初次提交'
如果闲每次添加文件麻烦,可以用 -a 参数跳过添加到暂存区的操作,直接在提交的时候把所有已经跟踪的文件上传。
git commit -a
撤消操作
有时候,在提交了之后发现有几个文件没有提交,可以用
git commit --amend
Github 远程代码仓库的使用
查看当前目录下的远程仓库 URL
$ git remote -v
diary git@github.com:KyleBing/Diary.git (fetch)
diary git@github.com:KyleBing/Diary.git (push)
在URL前面如果显示 origin 那是 git 给 URL 仓库的默认名字,
添加远程仓库
git remote add tb git@github.com:KyleBing/TouchbarBBT.git
这样就添加了 git@github.com:KyleBing/TouchbarBBT.git 的仓库,别名为 tb
这时候拉取远程仓库内容的时候,直接用 tb 代替 git@github.com:KyleBing/TouchbarBBT.git
从远程仓库拉取内容
git fetch [仓库别名]
这个指令会拉取远程仓库的所有内容,包括所有分支。
git pull
会拉取远程分支到当前分支,并自动合并。
推送到远程仓库
git push [仓库别名] [分支名]
会将你的项目推送到远程
查看远程仓库
git remote show [仓库别名]
在没有设置仓库别名的时候,git 会默认把这个仓库命名为 origin
git remote show tb
- remote tb
Fetch URL: git@github.com:KyleBing/TouchbarBBT.git
Push URL: git@github.com:KyleBing/TouchbarBBT.git
HEAD branch: master
Remote branch:
master tracked
Local ref configured for ‘git push’:
master pushes to master (local out of date)
给远程仓库重命名
git remote rename origin tb
重命名 origin 为 tb
移除远程仓库 tb
git remote rm tb
分支
如果项目中新建了三个文件,在提交的时候,Git 仓库中有五个对象:
三个 blob 对象(保存着文件快照
一个树对象(记录着目录结构和 blob对象索引)
一个提交对象(包含着指向前述树对象的指针和所有提交信息)
HEAD、 分支 master 是什么东西
git 的分支,其实是指向不同提交版本的指针。在 git init 初始化的时候,默认生成了一个名为 master 的分支,其实它跟其它分支的等级是一样的,都只是一个分支,默认名为 master,只是我们都懒得给它改名罢了。
git 还有一个名为 HEAD 的指针,作用是指向当前本地库正在的修改的分支,如上图,本地库正在 master 分支上做修改。
创建分支
git branch testing
上面的指令的结果如上图,在当前版本上新建了一个名为 testing 的分支。
git branch 只是创建一个分支,并不会切换到该分支。
分支切换
git checkout testing
上述操作会把 HEAD 指针指向 testing 分支,作用如下图:
当前在 testing 分支上,现在新建并提交一个文件,只会保存在 testing 分支上,而 master 分支还停留在前一个提交状态上,也就是说该文件只存在于 testing 分支上。
效果如下图;master 没有动,testing 已经向前移动到了最新的节点。
切换分支的时候会改变本地的目录结构
切换分支的时候,本地文件会变到当前分支的目录结构上,如果由于特殊原因没法切换分支的时候,会提示切换分支失败。
此时我们再切换回 master 分支并做修改后提交,master 指针就会指向新的提交节点。此时,master testing 分别处于不同的提交节点上,如下图:
git log --online --graph --all
terminal 界面效果如图:
分支的新建与合并
工作中的常见情景:
开发一个项目
为一个新的需求,创建一个分支,
在新建的分支上开展工作
正常开发过程中,如果出现了一个严重问题,需要紧急修补,可以这么做:
切换到你线上的主分支
为紧急任务新建一个分支,在这个分支上修复这个问题
在测试通过后,回到主分支上,并把解决问题的分支合并到主分支上
回到工作的分支,继续工作
新建分支
如果项目已经有了一定的提交记录,当前状态是下面这样:
为了修复一个问题编号是 #53 的问题,需要新建一个分支并在这个分支上开始修复工作
git checkout -b iss53
上面的命令是下面两条指令的简写
git branch iss53
git checkout iss53
你已经在分支 iss53 上做了一定的修改并提交了,此时的仓库是这样的:
此时,公司又有问题需要修改,不必把 iss53 和新问题混在一起修改,直接在原有 master 分支上新建一个分支并在其上面修改即可。
切换到 master 分支
git checkout master
创建新问题分支 hotfix
git checkout -b hotfix
此时的仓库状态:
这样,你可以在任意分支之间切换,且不会影响主分支 master 的正常运行。
假如,现在已经解决了主线上的问题,需要把 hotfix 分支合并到主线上。需要先切换到主分支 master 上,然后执行合并 hostfix 的操作
切到 master 分支
git checkout master
合并 hotfix 分支
git merge hotfix
结果
Updating f42c576…3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
可以看到反馈信息中的 fast-forward 提示,这是因为 hotfix 是在 master 分支新建的,并在其基础上做的修改,他们的合并操作只需要 HEAD 指针执行简单的前移即可,如图:
hotfix 问题解决并合并到主分支之后,你要回到之前的 iss53 分支继续解决 #53 问题。在切回去之前,你应该先已合并的 hotfix 分支删除,因为合并之后 master 和 hotfix 指向了同一个位置,已经不需要 hotfix了,执行操作:
删除 hotfix 分支
git branch -d hotfix
仓库现在是这样的:
分支的合并
经过奋力修改后,解决了 #53 问题,需要把 iss53 合并到 master 主分支中
切换到 master 主分支
git checkout master
合并 iss53 分支到 master
git merge iss53
结果
Merge made by the ‘recursive’ strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
这次 merge 跟之前 hotfix 分支的合并并不一样。这是因为,master 分支所在提交并不是 iss53 分支所在提交的直接祖先,此时需要比对 master iss53 和 他们相交的 C2 进行合并:
上面的合并后,仓库是这样的:
合并后需要删除无用的分支
git branch -d iss53
遇到冲突时的分支合并
如果前面提到的 iss53 hotfix 两个分支都修改了同一个文件的同一个地方,那么在合并的时候,git自动合并就会失败,需要手动解决冲突:
合并 iss53
git merge iss53
结果
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
此时查看状态会显示有一个文件未合并(unmerged)
查看仓库当前状态
git status
结果
On branch master
You have unmerged paths.
(fix conflicts and run “git commit”)
Unmerged paths:
(use “git add …” to mark resolution)
both modified: index.html
no changes added to commit (use “git add” and/or “git commit -a”)
出现冲突的时候,git 会在冲突文件中添加标准的冲突标记符,像下面这样子:
HEAD 所指示的版本在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。 为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:
解决冲突之后,用 git add 添加冲突文件到暂存区,此时 git 会认为冲突已经解决,并移除冲突标记。查看状态
git status
结果
On branch master
All conflicts fixed but you are still merging.
(use “git commit” to conclude merge)
Changes to be committed:
modified: index.html
执行提交
git commit
结果
“Merge branch ‘iss53’
Conflicts:
index.html
It looks like you may be committing a merge.
If this is not correct, please remove the file
.git/MERGE_HEAD
and try again.
Please enter the commit message for your changes. Lines starting # with ‘#’ will be ignored, and an empty message aborts the commit. # On branch master # All conflicts fixed but you are still merging. # # Changes to be committed: # modified: index.html
分支管理
git branch 命令不只是创建和删除分支,不加参数时会列出所有分支
查看分支列表
git branch
结果
iss53
- master
testing - 表示当前 HEAD 指针的指向,也就是当前所处的分支。
查看分支最后提交
git branch -v
结果
iss53 93b412c fix javascript issue
- master 7a98805 Merge branch ‘iss53’
testing 782fd34 add scott to the author list in the readmes
查看已合并的和未合并的分支
git branck --merged
结果
iss53
*master
可以看到当前 iss53 已合并到 master 中,可以删除 iss53 分支了。
当分支没有合并时,执行删除分支操作会失败:
git branch -d testing
结果
error: The branch ‘testing’ is not fully merged.
If you are sure you want to delete it, run ‘git branch -D testing’.
转载自:https://segmentfault.com/a/1190000018328949