Git 学习文档

#########################################################

Study Document for Git

#########################################################

Git 基础

Git 文件的三种状态: 已提交(committed)、已修改(modified)和已暂存(staged)。
Git 工作目录的状态: 已跟踪和未跟踪。

已提交表示数据已经安全的保存在本地数据库中。 已修改表示修改了文件,但还没保存到数据库中。 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。

基本的 Git 工作流程如下:

  1. 在工作目录中修改文件。
  2. 暂存文件,将文件的快照放入暂存区域。
  3. 提交更新,找到暂存区域的文件,将快照永久性存储到 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文件在工作区的修改全部撤销,这里有两种情况:

  1. file 自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
  2. 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 的远端分支名>

cherry pick

  1. 先clone一个全新代码
  2. Gerrit链接上Download里面checkout (cherry pick)
    cherry-pick:
    git fetch "https://*** && git cherry-pick FETCH_HEAD

3 git pull --rebase
4.正常改代码
5 .git add
6.git cherry-pick --continue
7.git commit --amend --reset-author
8.git push origin HEAD:refs/for/master

git commit reset

撤销 git commit --amend 误操作:

git reset HEAD@{1} 

commit code to github

echo "# qiuniu" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/hxia043/qiuniu.git
git push -u origin main

合并 commit

方法 1: git commit --amend
方法 2: squash

step1: git rebase -i HEAD~2
step2: change pick to s (squash)
step3: modify commit message
step4: git push...

详细 link: https://zhuanlan.zhihu.com/p/462530860

合并 commit 之后 push 代码:
gerrit:
git commit --amend

gitlab:
git push origin --force

Q&A

  1. error: src refspec master does not match any

问题原因是没匹配到master分支,所以用 git push 提交到远程分支的时候指定分支为 main 就好:git push -u origin main

参考网站:

Git - Book: https://git-scm.com/book/zh/v2

Learn Git Branching: https://learngitbranching.js.org/?demo

廖雪峰的官方网站 Git: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000

posted @ 2019-01-13 16:51  hxia043  阅读(301)  评论(0编辑  收藏  举报