#########################################################
Study Document for Git
#########################################################
Git 基础
Git 文件的三种状态: 已提交(committed)、已修改(modified)和已暂存(staged)。
Git 工作目录的状态: 已跟踪和未跟踪。
已提交表示数据已经安全的保存在本地数据库中。 已修改表示修改了文件,但还没保存到数据库中。 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
基本的 Git 工作流程如下:
- 在工作目录中修改文件。
- 暂存文件,将文件的快照放入暂存区域。
- 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
Git 语法
设置 Git 的配置
git config --list
git config --global user.name ***
git config --global user.email @.com
git help
git help verb
git verb --help
克隆远端仓库
git clone url
检查当前文件状态
git status
列出当前分支和文件的状态:已跟踪/未跟踪。
[***@*** deployment]$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# test.md
nothing added to commit but untracked files present (use "git add" to track)
跟踪新文件
git add file
[***@*** deployment]$ git add test.md
[***@*** deployment]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD file..." to unstage)
#
# new file: test.md
#
Changes to be committed: 已暂存状态。
修改已跟踪的文件
[***@*** deployment]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: test.md
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: test.md
#
Changes not staged for commit: 已跟踪文件的内容发生了变化,但还没有放到暂存区。
test.md 文件即出現在暂存区也出現在非暂存区,是因为暂存区存储的是经过 git add 的版本,如果此时 git commit ,则提交的是 git add 的版本,而不是当前改动的版本。
添加内容到下一次提交中
git add file
跟踪新文件。
把已跟踪的文件放到暂存区。
用于合并时把有冲突的文件标记为已解决状态。
查看已暂存和未暂存的修改
git diff
默认是比较工作目录中当前文件和暂存区域快照之间的差异。
git diff --staged
查看已暂存的将要添加到下次提交里的内容。
[***@*** deployment]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: test.md
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: test.md
#
[***@*** deployment]$ git diff
diff --git a/test.md b/test.md
index 2995e5e..8da0375 100644
--- a/test.md
+++ b/test.md
@@ -1,3 +1,5 @@
this is a test file for git study
a test file for git
+
+change version
[***@*** deployment]$ git add test.md
[***@*** deployment]$ git diff
[***@*** deployment]$ git diff --staged
diff --git a/test.md b/test.md
new file mode 100644
index 0000000..8da0375
--- /dev/null
+++ b/test.md
@@ -0,0 +1,5 @@
+this is a test file for git study
+
+a test file for git
+
+change version
[***@*** deployment]$
git show
show 出每次代码提交的改动
提交更新
git commit -m "..."
-m: 添加提交說明。
-a: 自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤。
git commit 提交时记录的是放在暂存区域的快照。 任何还未暂存的仍然保持已修改状态,并未被提交。
移除文件
Git 中移除某个文件,就必须要从已跟踪文件清单中移除。
rm file
git rm file
将暂存区中文件状态设为 Changes not staged for commit , 未暂存,然后使用 git rm 刪除该文件,不再对该文件进行跟踪。
[***@*** deployment]$ rm test1.md
[***@*** deployment]$ ls
BB1 BB2 BB3 buildscript meta-deployment README.md
[***@*** deployment]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: test1.md
#
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: test1.md
#
[***@*** deployment]$ git rm test1.md
rm 'test1.md'
[***@*** deployment]$ git status
# On branch master
nothing to commit, working directory clean
git rm -f file
强制删除暂存区中的文件,不再对该文件进行跟踪。
[***@*** deployment]$ ls
a.txt BB1 BB2 BB3 buildscript meta-deployment README.md
[***@*** deployment]$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: a.txt
#
[***@*** deployment]$ git rm -f a.txt
rm 'a.txt'
[***@*** deployment]$ git status
# On branch master
nothing to commit, working directory clean
移动文件
git move source target
相当于 mv source target, git rm source, git add target
查看提交历史
git log
git log -p
查看每次提交的內容差异
git log --decorate
查看各个分支当前所指的对象
git log --pretty=oneline
将每个提交放在一行显示
撤消操作
git commit --amend
将暂存区中的文件提交。如果自上次提交以来未做任何修改那么快照会保持不变,所修改的只是提交信息。
如果提交后发现忘记了暂存某些需要的修改,可使用以下命令重新提交:
git status
git log
git add file
git commit --amend
最终只会有一个提交,即第二次提交将代替第一次提交的结果。
撤消对文件的修改
git checkout -- file
命令 git checkout -- file 意思就是,把 file文件在工作区的修改全部撤销,这里有两种情况:
- file 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
- file 已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
[***@*** deployment]$ git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 1 different commit each, respectively.
# (use "git pull" to merge the remote branch into yours)
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: test.md
#
no changes added to commit (use "git add" and/or "git commit -a")
[***@*** deployment]$ git checkout -- test.md
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 1 different commit each, respectively.
# (use "git pull" to merge the remote branch into yours)
#
nothing to commit, working directory clean
取消暂存的文件
git reset HEAD file
当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令 git reset HEAD file,就回到了撤消对文件的修改,第二步按 git checkout -- file 操作。
[***@*** deployment]$ git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 1 different commit each, respectively.
# (use "git pull" to merge the remote branch into yours)
#
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: test.md
#
[***@*** deployment]$ git reset HEAD test.md
Unstaged changes after reset:
M test.md
[***@*** deployment]$ git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 1 different commit each, respectively.
# (use "git pull" to merge the remote branch into yours)
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: test.md
#
no changes added to commit (use "git add" and/or "git commit -a")
[***@*** deployment]$ git checkout -- test.md
[***@*** deployment]$ git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 1 different commit each, respectively.
# (use "git pull" to merge the remote branch into yours)
#
nothing to commit, working directory clean
远程仓库
git remote
查看已经配置的远程仓库服务器
git remote -v
显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL
远程仓库中获取数据
git fetch [remote-name]
访问远程仓库,从中拉取所有还没有的数据,它并不会自动合并或修改当前的工作,当准备好时必须手动将其合并入你的工作。
推送到远程仓库
git push [remote-name] [branch-name]
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先将他们的工作拉取下来并将其合并进你的工作后才能推送。
查看远程仓库
git remote show [remote-name]
打标签
给提交打标签,以示重要性。
git tag
列出已有标签。
git tag show tagname
show 标签和提交记录。
git tag -a tagname commit_id
给提交记录打标签。
分支
git branch
show 出当前分支,分支前的 * 号表示 HEAD 指向该分支,也即是当前正处在该分支下。
git branch -v
show 出当前分支的最后一次提交
git branch branch_name
创建新分支
git branch -d branch_name
删除分支
git checkout branch_name
切换到分支
git checkout -b branch_name
-b 选项: 新建一个分支,并且切换到该分支,相当于 git branch / git checkout
git checkout master
git merge branch_name
将分支 merge 到 master 中, fast-forward 具有共同的祖先,仅仅是指针的移动。
如果是 merge 的开发历史从一个更早的地方开始的(即没有共同祖先),那么 Git 会做简单的多方合并来 merge 提交,注意这次 merge 有多个父提交。
此时如果分支修改的是共同的文件内容,那么 Git 会提示冲突,需要手动修改冲突内容。
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add file..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
请牢记,当你做这么多操作的时候,这些分支全部都存于本地。 当你新建和合并分支的时候,所有这一切都只发生在你本地的 Git 版本库中 —— 没有与服务器发生交互。
远程分支
远程引用是对远程仓库的引用(指针),包括分支、标签等。
git remote show remote-name
远程跟踪分支是远程分支状态的引用。 它们是你不能移动的本地引用,以 (remote)/(branch) 形式命名。
git fetch remote-name
抓取远程仓库有而本地没有的数据。当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本。 换句话说,这种情况下,不会有一个新的分支 - 只有一个不可以修改的 remote/branch 指针。
git merge remote/branch
将远程抓取的内容合并到当前所在的分支。
git pull
git fetch 命令从服务器上抓取本地没有的数据时,它并不会修改工作目录中的内容。 它只会获取数据然后让你自己合并。 然而, git pull 在大多数情况下它的含义是一个 git fetch 紧接着一个 git merge 命令。
git push remote branch
Git 自动将 branch 分支名字展开为 refs/heads/branch:refs/heads/branch,意味着,“推送本地的 branch 分支来更新远程仓库上的 branch 分支。”
如, git push origin HEAD:refs/for/master
git branch -vv
将所有的本地分支列出来并且包含更多的信息,如每一个分支正在跟踪哪个远程分支与本地分支是否是领先、落后或是都有。
变基
Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase。
merge 将两个分支的最新快照以及二者最近的共同祖先进行三方合并,合并的结果是生成一个新的快照(并提交)。
变基 rebase 命令将提交到某一分支上的所有修改都移至另一分支上。
git checkout rebase-branch
git rebase target-branch
git checkout target-branch
git merge rebase-branch
变基的原则: 只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作。
git pull --rebase
git pull = git fetch + git merge
git pull --rebase = git fetch + git rebase
orginal:
modified:
git pull:
git pull --rebase:
rebase 操作可以把本地未 push 的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比;
切到远端分支
git branch --remote: show 出远端分支
git checkout --track <show 的远端分支名>
参考网站:
Git - Book: https://git-scm.com/book/zh/v2
Learn Git Branching: https://learngitbranching.js.org/?demo
廖雪峰的官方网站 Git: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000