Git学习笔记(本地)

本文详细介绍了Git的优势和常用命令,包括git init、git status、.gitignore、git add、git commit、git diff、git rm、git mv、git log、git reset、git checkout等。通过实例演示了如何在Git中初始化项目、管理文件状态、忽略文件、提交更改、查看历史记录、回滚版本等操作。还探讨了分支管理,如git branch、git merge和git rebase,以及解决合并冲突的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Git优势

传统版本控制工具如CVS,SVN等都是集中式版本控制,版本库集中存放在中央处理器中。而Git实现的是分布式版本控制,每个人的电脑上都有一个完整的版本库,这样设计主要有两点好处:

  1. 脱机状态下也能获取历史版本信息。
  2. 避免了单点故障问题。

Git常用命令

git init

使用git init可以将一个文件夹初始化为一个Git项目,初始化完成后该文件夹中会有一个新的隐藏文件夹.git

如:将C:\git初始化为一个Git项目。

$ cd C:\git

$ git init
Initialized empty Git repository in C:/git/.git/

 

git status

一个Git项目可以分为三个部分:工作区、暂存区和版本库。
工作区 就是当前工作区域,即Git文件夹中的文件。
暂存区 在隐藏文件夹.git中,位于工作区和版本库之间,用于缓存工作区中待提交的文件。
版本库 是最终区域,每次提交到版本库的内容都会被保存为项目的一个版本。

如:在C:\git中新建一个文件夹test.txt,用git status查看

$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        test.txt

nothing added to commit but untracked files present (use "git add" to track)

.gitignore

一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。

如:忽略所有以 .o 或 .a 结尾的文件

$ cat .gitignore
*.[oa]

 

git add

git add命令将工作区中的某项内容复制到暂存区中。

如:将上面添加的C:\git\test.txt添加到暂存区中。

$ git add test.txt

$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   test.txt

 

git commit

git commit命令将暂存区中的内容提交到到版本库中,用HEAD指针指向该版本,表示其为当前版本。
执行git commit后会弹出文本框,在其中输入相应提交的说明。或用git commit --m "XXX"来提交较短的说明。

如:将上面缓存的C:\git\test.txt添加到版本库中。

$ git commit
[master (root-commit) 62beab5] new text
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test.txt

$ git status
On branch master
nothing to commit, working tree clean

git commit -a命令允许跳过git add,将所有被track过的文件暂存并提交到版本库。
git commit -amend命令提交暂存区覆盖当前HEAD指针指向的版本,是git commit的“后悔药”。
 

git diff

gid diff命令将暂存区中的内容看作原来的版本,将工作区中的内容看作现在的版本,比较他们的区别。

如:修改C:\git\test.txt中的内容,调用git diff查看区别

$ git diff
diff --git a/test.txt b/test.txt
index e69de29..88c6620 100644
--- a/test.txt
+++ b/test.txt
@@ -0,0 +1 @@
+something new
\ No newline at end of file

gid diff --cachedgit diff --staged命令用于比较暂存区和版本库中最新版本之间的区别

如:将修改后的C:\git\test.txt中的内容add到暂存区,调用git diff --cached查看区别,再将暂存区commit,调用git diff --cached查看。

$ git diff --staged

$ git add "test.txt"

$ git diff --cached
diff --git a/test.txt b/test.txt
index e69de29..88c6620 100644
--- a/test.txt
+++ b/test.txt
@@ -0,0 +1 @@
+something new
\ No newline at end of file

$ git commit
[master 5a76c73] change 1
 1 file changed, 1 insertion(+)

$ git diff --cached

 

git rm

git rm用于从工作区和暂存区中删除指定的文件,即让Git不再跟踪指定文件。

如:删除C:\git\test.txt,调用git statusgit diff查看,用git rm删除暂存区中的test.txt,再次查看,最终用git commit提交该修改。

$ rm "test.txt"

$ git status
On branch master
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:    test.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git diff
diff --git a/test.txt b/test.txt
deleted file mode 100644
index 88c6620..0000000
--- a/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-something new
\ No newline at end of file

$ git rm "test.txt"
rm 'test.txt'

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    test.txt

$ git diff

$ git commit
[master 255b6f5] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

git mv

git mv "old" "new"命令用于对工作区和暂存区中的文件进行重命名操作,其相当于三条指令:

  1. mv "old" "new"
  2. git rm "old"
  3. git add "new"

git log

git log命令用于所有显示历史版本信息,每个版本号是通过SHA1计算出的一个大数。

$ git log --pretty=oneline
2c056afb902361dab926a5c31a206b9199b70708 (HEAD -> master) delete
5a76c73329d8f1f9f4a3af9094515159eb91cf4c change 1
62beab5d681565e2671dcba8b65f6a94da59f22b new text

 

git reset

git reset命令可实现在不同版本穿梭。
具体如:
git reset HEAD~x回退到Head指针的前x个版本。
git reset 62beab5回退到以62beab5开头的版本号所指的版本。
git resrt --soft HEAD~HEAD指针指向HEAD之前的一个版本。
git reset --mixed HEAD~git reset HEAD~HEAD指针指向HEAD之前的一个版本,并将现所指的版本同步到暂存区中。
git reset --hard HEAD~HEAD指针指向HEAD之前的一个版本,并将现所指的版本同步到暂存区和工作区中。

验证soft,mixedhard的区别:

$ git reset --soft HEAD~

$ git diff

$ git diff --cached
diff --git a/test.txt b/test.txt
deleted file mode 100644
index 88c6620..0000000
--- a/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-something new
\ No newline at end of file

$ git reset 2c056a

$ git reset HEAD~
Unstaged changes after reset:
D       test.txt

$ git diff
diff --git a/test.txt b/test.txt
deleted file mode 100644
index 88c6620..0000000
--- a/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-something new
\ No newline at end of file

$ git diff --cached

$ git reset 2c056a

$ git reset --hard HEAD~
HEAD is now at 5a76c73 change 1

$ git diff

$ git diff --cached

此外,git reset “version" "path"会跳过移动HEAD指针这一步,将版本version中的path所指的文件覆盖到暂存区。带有path的命令只能是--mixed级别。
 

git checkout

git checkout命令用于分支切换,详见git branch命令。

git checkout – “filename”

git checkout -- "filename"是让暂存区中的内容同步到工作区。

$ git status
On branch master
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.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git checkout -- "test.txt"

$ git status
On branch master
nothing to commit, working tree clean

git branch

git branch 用于显示所有分支。
git branch “bname" 用于创建一个新的分支。
git branch -d 用于删除一个分支。

分支

个人理解,版本库是使用一个类似于LinkedHashMap的数据结构存储各版本。前面提到HEAD指针用于指向当前的版本,其实这并不完全正确。在用git log时,可以看到有(HEAD -> master)的字样,可见HEAD指针指向的是一个叫做master的东西,这个master才指向一个版本号。那么这个master是什么呢?
这个master就是一个分支,Git 给主分支的默认名字就叫master,就像第一个远程仓库的默认名字是origin 一样。HEAD指针指向一个分支指针,表示当前所在的分支,再由分支指针指向版本号。在Git中,创建一个分支就是创建一个指针,而切换分支就是移动HEAD指针。
可以想象当版本库中不只有一个分支时,不同的分支向不同的方向发展,版本库中的线性结构会变成树状结构。

git checkout 命令用于切换分支。
git checkout -b 命令用于创建并切换到该分支,相当于git branch + git checkout
git checkout -b "bname1" "bname2" 可以以一个远端的分支为模板创建一个本地分支。
注意:当工作区或暂存区有未提交的修改时,不能随意切换分支,会报如下错误:

$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
        test.txt
Please commit your changes or stash them before you switch branches.
Aborting

git stash

上文提到,工作区或暂存区有未提交的修改时不能随意切换分支。那当工作区或暂存区的修改不足以commit,但又不能删除时,就需要用到git stash命令。
git stash命令可以处理工作目录的脏的状态 (修改的跟踪文件与暂存改动),然后将未完成的修改保存到一个栈上,你可以在任何时候重新应用这些改动。

git stash list 用于显示stash栈中的所有内容。
git stash apply 用于应用栈中的修改。
git stash drop 用于丢弃栈中元素。
git stash pop 应用修改并丢弃。

git merge

git merge "branchName" 用于将某分支合并到当前分支。
可以想象,合并时有两种情况:
1.待合并分支是当前分支所指版本的直接上游,如下:

* c1e9a79918c87c85369a5989ccef6b98a441ba3f (newBranch) 2nd change
* 044cf1bd7915a9c379b2cc05d25f26789ec6eeaf (HEAD -> master) 1st change

此时执行git merge "branchName",向前移动当前分支指针即可:

$ git merge newBranch
Updating 044cf1b..c1e9a79
Fast-forward
 test.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git log --graph --pretty=oneline
* c1e9a79918c87c85369a5989ccef6b98a441ba3f (HEAD -> master, newBranch) 2nd change
* 044cf1bd7915a9c379b2cc05d25f26789ec6eeaf 1st change

我们看到提示中的Fast-Forward字样,意思是简单将指针快进,但是这种快进式的合并存在一个问题:删除分支后,会丢掉分支信息。如果想保留分支信息,可以加上--no-ff选项。

$ git merge --no-ff -m "merge with no conflict" newBranch
Merge made by the 'recursive' strategy.
 test.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git log --pretty=oneline --graph
*   2f6b28377a56915165bf7f9d8572cd6ecba622db (HEAD -> master) merge with no conflict
|\
| * c1e9a79918c87c85369a5989ccef6b98a441ba3f (newBranch) 2nd change
|/
* 044cf1bd7915a9c379b2cc05d25f26789ec6eeaf 1st change
* eb4e818f28467c2eaf60d5e071304ea2dc4d29b3 change to 3
* 87806f775eee0c8f01ef46dce18e11074b4b51ce branch master

2.两个分支都有自己新的提交,此时merge会报conflict

$ git merge newBranch
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Automatic merge failed; fix conflicts and then commit the result.

根据提示要fix conflicts,打开文件看到以下内容:

<<<<<<< HEAD
123
=======
12
>>>>>>> newBranch

这是git把两个分支冲突的部分标识出来,简洁易懂。
将文件改成期望的合并后的内容,commit,即可修复冲突。

$ git commit -a -m "merge"
[master c3c2340] merge

$ git log --pretty=oneline --graph
*   c3c234078b569d04b714e3f25e1ce151bf994b47 (HEAD -> master) merge
|\
| * c1e9a79918c87c85369a5989ccef6b98a441ba3f (newBranch) 2nd change
* | 51d603739fc50001daa6c2e10f57393e888f1e31 3rd change
|/
* 044cf1bd7915a9c379b2cc05d25f26789ec6eeaf 1st change
* eb4e818f28467c2eaf60d5e071304ea2dc4d29b3 change to 3
* 87806f775eee0c8f01ef46dce18e11074b4b51ce branch master

git rebase

git rebasemerge的作用类似,也是用于分支间的合并。但变基不会保留原来的分支形式,而将两个分支整合为一个分支。变基主要用于在本地合并分支时整合形式,避免提交到远程仓库后分支太多过于混乱。
merge一样,合并时会出现冲突:

$ git rebase newBranch
First, rewinding head to replay your work on top of it...
Applying: 3rd change
error: Failed to merge in the changes.
Using index info to reconstruct a base tree...
M       test.txt
Falling back to patching base and 3-way merge...
Auto-merging test.txt
CONFLICT (content): Merge conflict in test.txt
Patch failed at 0001 3rd change
The copy of the patch that failed is found in: .git/rebase-apply/patch

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

打开文件,发现和merge出现冲突时效果一摸一样:

<<<<<<< HEAD
123
=======
12
>>>>>>> newBranch

将文件改成期望的合并后的内容,根据提示git addgit rebase --continue

$ git add "test.txt"

Admin@DESKTOP-UD83S84 MINGW64 /c/git (master|REBASE 1/1)
$ git rebase --continue
Applying: 3rd change

Admin@DESKTOP-UD83S84 MINGW64 /c/git (master)
$ git log --pretty=oneline --graph
* 5e47d0da06b5d526963f444d7f1f37df2dc5b963 (HEAD -> master) 3rd change
* c1e9a79918c87c85369a5989ccef6b98a441ba3f (newBranch) 2nd change
* 044cf1bd7915a9c379b2cc05d25f26789ec6eeaf 1st change
* eb4e818f28467c2eaf60d5e071304ea2dc4d29b3 change to 3
* 87806f775eee0c8f01ef46dce18e11074b4b51ce branch master

发现两个分支已经被合并到一个分支中,且没有保留原来的分支格式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值