Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
windows安装:进入网站 https://git-scm.com/ 安装,ubuntu配置:apt install git。当前于 Win 下已安装 Git 版本 2.40.1。
一般工作流程如下:
通常我们执行的操作为:1. 在工作目录中添加、修改文件;2. 将需要进行版本管理的文件放入暂存区域;3. 将暂存区域的文件提交到 Git 仓库。相对应的,Git 管理的文件有三种状态:已修改(modified)、已暂存(staged)和已提交(committed)。
下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系:
图中的 objects 标识的区域为 Git 的对象库,实际位于 “.git/objects” 目录下,里面包含了创建的各种对象及内容。
当对工作区修改(或新增)的文件执行 git add
命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
当执行提交操作(git commit
)时,暂存区的目录树写到本地仓库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
当执行 git reset HEAD
命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
当执行 git rm --cached
命令时,会直接从暂存区删除文件,工作区则不做出改变。
当执行 git checkout .
或者 git checkout --
命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区中的改动。
当执行 git checkout HEAD .
或者 git checkout HEAD
命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
Git 使用 git init 命令来初始化一个 Git 仓库,在执行完成 git init 命令后,Git 仓库会生成一个 .git 目录,该目录包含了资源的所有元数据,其他的项目目录保持不变。
直接使用。
git init newrepo
会在 newrepo 目录下出现 .git 目录。
用来进行 git 的设置,显示当前的 git 配置信息:git config --list
;git config --global --list
。来带有参数 --global 表示针对所有仓库有效。
设置提交代码时的用户信息:
$ git config --global user.name "abc"
$ git config --global user.email "[email protected]"
可以查看在自上次提交之后是否有对文件进行再次修改。
用于查看 Git 仓库中提交历史记录。它显示了从最新提交到最早提交的所有提交信息,包括提交的哈希值、作者、提交日期和提交消息等。
示例:如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:
$ git add *.c
$ git add README
$ git commit -m '初始化项目版本'
添加文件/目录到暂存区。git add
或者git add
。
其中在 git2中, git add . 等同于 git add -A:表示会监控工作区的状态树,它会把工作区的所有变化提交到暂存区,包括修改(modified)、新文件(Untracked files)、删除的文件(deleted)。 但使用 .
在 git1.x 中`不会监控删除的文件。
在 git 提交时碰到如下警告:
$ git add hello.cpp
warning: in the working copy of 'hello.cpp', LF will be replaced by CRLF the next time Git touches it
$ git config --global core.autocrlf true
是因为换行符在不同平台上的表示不同。
应用情况:
影响:
在 Windows 下,通过设置 core.autocrlf=true ,Git 可以在你提交时自动地把回车(CR)和换行(LF)转换成换行(LF),而在检出代码时把换行(LF)转换成回车(CR)和换行(LF)。
$ git config --global core.autocrlf true
提交暂存区的指定文件到本地仓库。git commit file1,file2..-m [message]
,其中 file1,file2是可选的,如果为空时,表示提交整个暂存区到本地仓库;message 可以是一些备注信息,在 Linux 下使用单引号 '
,在 win 下使用双引号"
。
在 commit 提交时,会显示出提交者的信息,名称和邮箱。这两个信息 git 会自动生成,如果需要显示修改的话,采用 git config --global user.name "Your Name" 和 git config --global user.email [email protected]
。
如果觉得 git add 提交缓存的流程太过繁琐,Git 也允许用 -a 选项跳过这一步,等同于先执行 git add . 再执行 git commit -m “message”。如下
$ git commit -am "message"
其用法为:git clone
,repo: 远程仓库,或者是本地目录。directory: 目标目录名称。directory 为可选项,为空的话默认在当前目录拷贝一份远程仓库的完整内容。
在远程连接时,一般可以通过 https 和 ssh 来拉取代码,采用 https 时: git clone https克隆地址,需要在弹出的对话框中输入远程仓库的用户名和密码;使用 ssh 时则需要配置 ssh 公钥,公钥添加进远程仓库,私钥用来识别当前操作的用户身份。
ssh 密钥生成可参考:先在 Bash 中生成密钥对,然后将公钥添加到 Gitee 账户中即可,第一次远程连接时,会有提示,只需要输入yes即可,如下:
$ git clone [email protected]:cedirczou/mini-pm.git
Cloning into 'mini-pm'...
The authenticity of host 'gitee.com (180.76.198.77)' can't be established.
ED25519 key fingerprint is SHA256:+ULzij2u99B9eWYFTw1Q4ErYG/aepHLbu96PAUCoV88.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'gitee.com' (ED25519) to the list of known hosts.
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (6/6), done.
用来删除文件。
git rm file
:将文件从暂存区和工作区中删除 -f 表示强制删除。
git rm -cached file
:将文件从暂存区域移除,但仍保留在当前工作区中。
用于移动或重命名一个文件、目录或软连接。用法同 mv 命令。
Git 分支:
在版本控制过程中,同时推进多个任务,我们就可以创建每个任务单独的分支。使用分支意味着可以把自己的工作从开发主线上分离开,开发自己分支的时候,不会影响主线分支的运行。分支可以简单的理解为副本,一个分支就是一个单独的副本(分支底层其实也是指针的引用)
在 master 这个主线上运行,运行的同时要增加功能,那我们就可以把master复制一份出来,在复制的地方进行开发,开发完之后在对 master 进行合并更新;当我们引入的新功能有 bug 时,就可以从 master 分支再引一个分支 hot-fix (热修复分支),对代码进行修改,修改后再合并到 master 。
下图是常见的 Git 分支模型:
git branch:不带参数时,git branch 会列出你在本地的分支。 前面带有 * 的是当前分支;git branch -a 会列出全部分支(本地和远程)。当执行 git init 的时候,默认情况下 Git 就会为你创建 master 分支。
git branch branchname:创建一个名为 brachname 的分支。
git branch -d branchname:删除分支 brachname。
git checkout branchname:切换分支,当切换分支的时候,Git 会用该分支的最后提交的快照替换当前工作目录的内容, 所以多个分支不需要多个目录。
git checkout -b branchname:创建一个新分支并立即切换到该分支下。
不同分支之间的内容相互独立,这仅限于在 commit 之后,在这之前,不管在哪个分支创建的文件,所有分支都能看到该文件,而这个文件归属于谁呢?归属于第一个执行 add 和 commit 的分支。
$ ls
README.en.md README.md
$ git branch
* master
$ git checkout -b dev
Switched to a new branch 'dev'
$ ls
README.en.md README.md
$ echo "hello,dev." > dev.txt
$ ls
README.en.md README.md dev.txt
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ ls
README.en.md README.md dev.txt
$ git checkout dev
Switched to branch 'dev'
$ ls
README.en.md README.md dev.txt
$ git add dev.txt
$ git commit -m "new dev"
...
1 file changed, 1 insertion(+)
create mode 100644 dev.txt
$ ls
README.en.md README.md dev.txt
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ ls
README.en.md README.md
--------------------------------------------------------------------
$ git checkout dev
Switched to branch 'dev'
$ vim abc.c
$ ls
README.en.md README.md abc.c dev.txt
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
$ ls
README.en.md README.md abc.c
$ git add abc.c
$ git commit -m "new abc"
...
1 file changed, 5 insertions(+)
create mode 100644 abc.c
$ ls
README.en.md README.md abc.c
$ git checkout dev
Switched to branch 'dev'
$ ls
README.en.md README.md dev.txt
git merge:合并分支。可将任何分支合并到当前分支中去,它只会影响当前分支,不会影响其他分支。默认采用 fast-forward 策略。它有一些常用的参数如:
git merge --no-commit maint
·
将分支maint
合并到当前分支中,但不要自动进行新的提交。
git merge -s ours obsolete
合并obsolete
分支到当前分支,使用ours
合并策略。
git merge fixes enhancements
合并分支fixes
和enhancements
在当前分支的顶部,使它们合并。
git merge dev
将分支dev
合并到当前分支中,自动进行新的提交。
Git 在合并分支时,会分别将两个分支的 commit 记录(每一次 commit 提交时所做的操作),相对于当前需要合并的两个分支最近一次相同版本记录 base 进行比较。如果:
如果在 master 下进行:
git merge dev
会提示 Already up to date.,即 master 不会发生变化。
如果在 dev 下进行:
git merge master
那么会将在 master 最近提交过程中所做的更改全部实施在 dev 分支上,最终在 dev 上看到的即是 master 的全部内容。
如果将 dev 合并到 master 上面:
git merge dev
git 会以当前 master 分支项目代码为基础,然后将当前的 dev 项目代码和 base 做比较,将 dev 在 base 上的操作在 master 上在执行一遍。
将 master 合并到 dev 上的操作同上。
解决冲突示例:
$ git branch
* master
$ ls
README.md m.txt
$ git checkout -b dev
Switched to a new branch 'dev'
$ vim m.txt
$ cat m.txt
devdev
$ git add .
warning: in the working copy of 'm.txt', LF will be replaced by CRLF the next time Git touches it
$ git commit -m "dev modify"
[dev 5630f6b] dev modify
1 file changed, 1 insertion(+), 1 deletion(-)
$ ls
README.md m.txt
$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 27 commits.
(use "git push" to publish your local commits)
$ ls
README.md m.txt
vim m.t
$ vim m.txt
$ cat m.txt
mastermaster
$ git add .
$ git commit -m "master modify"
[master b0d554b] master modify
1 file changed, 1 insertion(+), 1 deletion(-)
$ git merge dev
Auto-merging m.txt
CONFLICT (content): Merge conflict in m.txt
Automatic merge failed; fix conflicts and then commit the result.
$ git diff
diff --cc m.txt
index 311d061,1291d09..0000000
--- a/m.txt
+++ b/m.txt
@@@ -1,1 -1,1 +1,5 @@@
++<<<<<<< HEAD
+mastermaster
++=======
+ devdev
++>>>>>>> dev
$ vim m.txt
$ cat m.txt
mastermaster
$ git add .
$ git commit -m "done"
[master e9fcf9f] done
$ git merge dev
Already up to date.
master 和 dev 分支相对于原来的 txt 都进行了修改,在 m.txt 中能够看到它们的修改变化,此时需要我们手动进行修改,选择保留哪一个分支的结果。在本例中保留 master 分支所做的修改,m.txt 中的内容改为 mastermaster,在重新进行 add commit 操作来提交我们所做的修改。
作用是将本地当前分支的代码合并到远程指定的分支上。命令格式为:git push <远程主机名> <本地分支名>:<远程分支名>
。
如果本地分支名与远程分支名相同,则可以省略冒号:git push <远程主机名> <本地分支名>
。如果本地版本与远程版本有差异,但又要强制推送可以使用 --force 参数:git push --force origin master
本地仓库可以和多个远程主机建立联系,如果没有特殊制定,就只有一个,名字默认为 origin。
$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 393 bytes | 393.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
...
$ git push
fatal: No configured push destination.
Either specify the URL from the command-line or configure a remote repository using
git remote add <name> <url>
and then push using the remote name
git push <name>
此时需要采用 git remote 来配置远程主机信息,其常用命令如下:
git remote -v
:列出当前仓库中已配置的远程仓库,并显示它们的 URL。
git remote add
:添加一个新的远程仓库。指定一个远程仓库的名称和 URL,将其添加到当前仓库中。 其中url 可以采用 https 或者 ssh。
git remote rm
:从当前仓库中删除指定的远程仓库。
通过 git remote add origin ssh_url 添加远程仓库之后,执行 git push -f origin master即可强制合并到远程仓库(用当前目录中的文件替换远程仓库)。
通常在远程主机新建仓库之后,先 clone 下来,然后在这个目录中对文件进行增加,删除和修改,然后在 add ----> commit,最后直接 git push 即可。
用于从远程主机获取分支代码且合并到本地的版本。它等同于 git fetch 和 git merge FETCH_HEAD 的简写。其中 git fetch 的作用是拉取远程主机的分支项目代码到本地。
命令格式为: git pull <远程主机名> <远程分支名>:<本地分支名>
将远程主机 origin 的 master 分支拉取过来,与本地的 brantest 分支合并。
git pull origin master:brantest
v如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
git pull origin master
pull - request 的含义指的是请求别人拉取自己修改后的代码。 具体可见:https://blog.csdn.net/wan212000/article/details/127387895