一、git概述
1.1安裝
windows版本
官方下载(比较慢):Git - Downloads
Linux版本
bashyum install git
查看git版本。
git --version
1.2创建仓库gitee
注册账号 Gitee - 基于 Git 的代码托管和研发协作平台
新建仓库 honey2024
配置
git config --global user.email "your_email@example.com"
git config --global user.name "username"
要查看 Git 的用户名和邮箱,你可以使用以下命令:
git config --global user.name
git config --global user.email
-
输入 git init 把这个目录变成一个 git 仓库
-
本地仓库跟远程的仓库建立连接
-
新建 .gitignore 文件
bash.idea node_modules *.iml
-
暂存代码 git add . (要注意当前的仓库是否存在旧的仓库文件夹 .git,如果存在要删除掉)
bash# 把当前目录除了 .gitignore描述之外的所有文件全部加入到暂存区 git add .
-
提交文件到本地仓库
bashgit commit -m '初次提交'
解决git bash 终端显示中文乱码
bash
git config --global core.quotepath false
6.推送代码到远程仓库
bash
git push -u origin "master"
强制覆盖远程仓库
git push -f origin "master"
总结
bash
# 配置
# 全局配置
git config --global user.email "your_email@example.com"
git config --global user.name "username"
# 仓库配置
git config user.email "your_email@example.com"
git config user.name "username"
git config --global --list
git config --list
# 新建仓库
git init
# 添加远程仓库
git remote add origin ''
# 查看远程仓库
git remote -v
# 添加文件到暂存区
git add .
# 查看状态
git status
# 忽略文件
.gitignore文件
# 提交
git commit -m 'init'
# 拉取远程代码
git pull origin master
# 强制推送代码到远程仓库
git push -f origin master
# 克隆代码
git clone ''
1.3idea配置git
如果idea终端输入git命令无法识别解决办法
Idea打开setting->搜索git->Version Control->Git->将Path to Git executable地址修改为->Git\cmd\git.exe
如下图
接着在上面搜索框中搜索tools->找到下面的Terminal->将Shell Path改为->Git\bin\bash.exe最后点击确认。
如下图:
bash
git init //初始化仓库
git add .(文件name) //添加文件到本地
git commit -m "first commit" //添加文件描述信息
git remote add origin 远程仓库地址 //链接远程仓库
git pull origin master // 把本地仓库的变化连接到远程仓库master 分支
git push -u origin master //把本地仓库的文件推送到远程仓库master 分支
idea开启远程
二、工作原理
2.1基本概念:工作区、暂存区、版本库、远程仓库
- 工作区(Workspace):本地存放文件的地方。Git会知道这里的文件变更,如添加/修改/删除文件。
- 暂存区(Stage/Index):临时存放文件变更 信息,事实上它是一个名为
index
的文件。- 版本库(Repository):工作区有一个隐藏目录
.git
,它是Git的版本库,为了与远程 仓库区分,将其明确称为本地 版本库(Local Repository)。其中有一个HEAD
指向当前版本库版本。- 远程仓库(Remote Directory):托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换。
2.2 Git文件操作
创建仓库(git init)
创建本地仓库的方法有两种:一种是本地创建全新仓库,另一种是克隆远程仓库
本地创建全新仓库,初始化一个版本库:
bash
git init
提交变更(git add, git commit)
下面介绍提交变更到本地版本库的基本流程。
准备工作:先新建一个目录learngit,并创建README.md文件,随便写入一句话。
bash
mkdir learngit
cd learngit
touch README.md
echo "# Hello, git!" >> README.md
添加文件变更到版本库,分两步:
- 使用命令
git add <file>
,可多次使用,添加多个文件。 - 使用命令
git commit -m <message>
,文件从暂存区提交到版本库;<message>
表示提交的信息。
bash
git init #初始化一个git的本地仓库
git add README.md #将工作区README.md文件的变更移动到暂存区
git commit -m "add README.md" #将暂存区提交到本地仓库
在IntelliJ IDEA中,"提交"对应于Git的**
git commit
命令,而"推送"对应于Git的git push
**命令。具体如下:
- 提交(Commit) :在IDEA中执行提交操作通常通过VCS菜单下的
Commit
选项或者快捷键Ctrl+K
来进行。这个操作会将你在本机工作目录中对文件所做的修改保存到本地的Git仓库中。提交时,你需要编写提交信息来描述本次提交包含的更改。- 推送(Push) :在IDEA中推送代码到远程仓库通常是通过VCS菜单下的
Push
选项进行。对应的Git命令是git push
,它会将本地仓库中的提交推送到配置好的远程仓库,如GitHub或GitLab等。在进行推送之前,需要确保本地仓库与远程仓库已经关联,并且设置了正确的远程仓库地址。需要注意的是,在实际操作中,为了确保其他人能够顺利拉取(Pull)你的更改,建议在推送之前先执行
git pull
或git fetch
来获取最新的远程更改,并解决可能出现的合并冲突。
管理变更(git add/rm, git restore)
理解:Git跟踪并管理的是变更,而不是文件。
-
撤销工作区变更(撤销对工作区文件的添加/修改/删除):
git restore <filename>
或git checkout -- <filename>
。 -
撤销暂存区变更(撤销git add/rm):
git restore --staged <filename>
或git reset HEAD <filename>
。
bash
echo "after git add" >> README.md #在工作区修改README.md,用git status可以看到被修改,但这一变更未加到暂存区
git add README.md #变更被加到暂存区
git restore --staged README.md #撤销暂存区的变更(README.md的修改),注意,此时工作区文件还是没有变
git restore README.md #撤销工作区的变更,即工作区README.md文件被还原成修改前
git rm README.md #在工作区删除README.md,并且这一变更被加到暂存区
git restore --staged README.md #撤销暂存区的变更(README.md的删除),注意,此时工作区文件还是没有变
git restore README.md #撤销工作区的变更,即工作区README.md文件被还原成删除前
相当于
在IntelliJ IDEA中,回滚操作对应于Git的
git reset
命令。具体来说,IntelliJ IDEA提供了一种直观的方式来回滚到特定的版本
版本回退(git reset)
Git允许我们在版本的历史之间穿梭,实际上就是移动HEAD指向的位置(HEAD指向的版本就是当前版本)。
用
git log
可以查看提交历史,即历史每次提交的<commit_id>,以便确定要回退到哪个版本。用
git reflog
可以查看命令历史,即所有分支的所有操作记录(包括commit
,reset
,checkout
,merge
等操作)。
指定版本到<commit_id>:
git reset --hard <commit_id> #当前分支和HEAD均指向<commit_id>
回退到当前HEAD的上一个commit,撤销暂存区变更(撤销commit和add):
git reset --hard HEAD~1 #HEAD~1表示上一个commit版本,如果是往上两个版本就是HEAD~2;当前版本就是HEAD
回退到当前HEAD的上一个commit,不撤销暂存区变更(撤销commit):
git reset --soft HEAD~1
查看命令(git status, git log, git reflog, git diff)
git status
查看git仓库中,工作区、暂存区、版本库的当前状态。git log
查看提交历史。可加选项:--oneline
每行 显示一个commit。例如显示9af21bf add README.md
,那么<commit_id>前几个字符就是9af21bf
。--all
显示所有分支的提交历史,否则只显示当前分支的提交历史。--graph
显示分支合并,以横线形式连接曾有过合并的各个提交。
git reflog
查看命令历史。git diff
查看工作区和暂存区差异。git diff --cached
查看暂存区和版本库差异。git diff -- HEAD~1
查看工作区和版本库的差异。HEAD~1
可以改成HEAD
、HEAD~2
等等。git diff HEAD HEAD~1
查看版本库HEAD
与版本库HEAD~1
之间的差异(最新的commit和上一次commit)。
git log相当于idea
git status
相当于idea
小结:提交变更 + 管理变更
本地仓库的各项管理命令可以参照下图方便记忆(从右往左看):
- 工作区变更:任意的添加/修改/删除文件。
- 撤销工作区变更:
git restore <filename>
或git checkout -- <filename>
。
- 撤销工作区变更:
git add
工作区→暂存区 添加文件变更。- 撤销add:
git restore --staged <filename>
或git reset HEAD <filename>
。
- 撤销add:
git commit
暂存区→版本库 提交文件变更。- 撤销commit:
git reset --soft <commit_id>
。 - 撤销commit和add:
git reset --hard <commit_id>
。
- 撤销commit:
2.3分支管理
查看/创建/切换/删除分支(git branch, git switch)
查看本地分支:
git branch #要查看远程分支则加上选项-r,查看所有分支则加上选项-a
创建分支:
git branch <name>
切换分支:
git switch <name> #等价于git checkout <name> (注意:switch命令是git 2.23版本的新命令)
创建+切换分支:
git switch -c <name> #等价于git checkout -b <name>
删除普通分支:
bash
git branch -d <name>
强制删除未合并的分支:
bash
git branch -D <name>
在IntelliJ IDEA中,查看、创建、切换和删除分支的操作具体如下:
- 查看分支:
- 通过主菜单
VCS
->Git
->Branches
,可以查看当前项目的所有分支情况。- 在
Version Control
窗口中,选择Log
选项卡,可以看到提交历史以及各个分支之间的关系。
- 创建分支:
- 在
Version Control
窗口中,选择Local Changes
选项卡,右键点击想要基于其创建分支的文件或目录,选择Git
->New Branch
。- 输入新分支的名称,然后IDEA会将更改保存到新分支上。
- 切换分支:
- 在
Version Control
窗口中,选择Local Changes
选项卡,找到你想要切换到的分支,右键点击并选择Checkout as New Branch
。- 如果需要切换到远程分支,可以通过
VCS
->Git
->Fetch
来先获取远程分支的最新信息,然后再进行切换。
- 删除分支:
- 在
Version Control
窗口中,选择Local Changes
选项卡,找到你想要删除的本地分支,右键点击并选择Git
->Delete Branch
。- 如果是远程分支,你需要先用
Push
操作将本地更改同步到远程仓库,然后再进行删除。
合并分支(git merge)
-
快速合并(Fast-forward):合并当前分支(旧)到某分支(新)的位置。
git merge <name> #某分支名为<name>
-
非快速合并:合并当前分支+某分支,产生一个新的提交,合并到这个新提交的位置,这样可以保存之前的分支历史。
git merge --no-ff -m <message> #<message>表示新提交的信息
操作示例:
首先创建并切换到分支feature,并在feature分支上进行一次提交。
bash
# 首先用git status看看是否位于分支master(如果不是就用git switch master先切换一下)
git switch -c feature #创建并切换到分支feature
echo "add merge" >> README.md #修改README.md
git add README.md
git commit -m "add merge" #提交
则此时状态如下图(蓝线表示master分支,红线表示feature分支):
然后,用git switch master
切换回master分支。此后,HEAD指向master。
接下来请任选(1)或(2)的命令全部执行一遍,即选择你的合并策略(Fast-forward 或 no-fast-forward)。
(1)快速合并
git merge feature
用git log --oneline --graph
显示历史提交信息如下:
* f7a06a2 (HEAD -> master, feature) add merge
* e0e4ca3 conflict fixed (注:这里是你上一次的提交信息,与合并无关)
合并后的状态如下图:
(2)非快速合并
git merge feature --no-ff -m "merge with no-ff"
用git log --oneline --graph
显示历史提交信息如下:
* fc7e0ee (HEAD -> master) merge with no-ff
|\
| * d4d0ec9 (feature) add merge
|/
* e0e4ca3 conflict fixed (注:这里是你上一次的提交信息,与合并无关)
合并后的状态如下图:
(选做)最后,可以用git branch -d feature
删除feature分支。
详情请见
bug分支(git stash, git cherry-pick)
假设现在有master, feature分支,你在feature分支上进行工作,写一个hello.py文件,并将其添加到了暂存区。
bash
git switch feature #切换到feature分支,如果没有这个分支就用git switch -c feature创建并切换
touch hello.py & echo "print('hello')" >> hello.py #创建了一个python代码文件并写入了内容
git add hello.py #将变动加至暂存区
git add
之后,用git status
可以看到"hello.py的变更处于待提交状态"。
此时,突然发现有一个紧急的bug需要修复,但hello.py还没有写完,暂时无法commit。
于是你打算创建一个新的bug分支,但当前分支的工作状态必须先保存下来,那么可以用:
git stash
git stash
可以把当前工作状态储存到stash这个栈之中,等以后出栈,即可还原现场,继续工作。
当前工作状态入栈后,再用git status
可以看到"无文件要提交,干净的工作区"。
假设要在feature分支上修复bug,那么就在feature分支上创建并切换到bug分支(命名为issue-101)。假设修复bug就是修改README.md文件,修复完就commit。
#现在位于feature分支进行操作,然后创建并切换到bug分支
git switch -c issue-101 #bug分支
echo "Fixed the bug of README.md" >> README.md
git add README.md
git commit -m "fix bug 101"
然后,再切换回feature分支,将bug分支与feature分支进行非快速合并:
git switch feature
git merge issue-101 --no-ff -m "merged bug fix 101"
那么此时,已经完成了bug修复,可以重返当时储存的工作状态了:
git stash pop #将栈顶的工作状态出栈,同时删除栈顶内容
到此为止,我们就完成了feature分支上bug的修复过程,总结一下流程:
- feature分支,用
git stash
保存工作状态。 - 切换到bug分支,修复完bug,
commit
。 - 切换回feature分支,将bug分支与feature分支合并。用
git stash pop
还原工作状态。
现在我们已经修复了feature分支上的bug,假设master分支上也要修复相同的bug,怎么办?
不用那么麻烦的再做一遍修复bug、合并分支的工作,可以用git cherry-pick <commit_id>
,它能把bug分支的commit操作直接"复制",然后commit到当前分支:
git switch master
git stash # 如果master分支上有待提交的变更,那么必须先保存状态
git cherry-pick 8436eb8 #8436eb8是修复bug的<commit_id>,可用git log查看为8436eb8 (issue-101) fix bug 101
git stash pop
(选做)如果你需要保存多个工作状态,可以多次入栈。想恢复某个工作状态的时候,先用git stash list
查看stash内容,再用git stash apply
恢复到指定的工作状态:
git stash list # 查看stash内容
git stash apply stash@{0} #栈顶为stash@{0},栈顶的下一个为stash@{1}
注意:git stash apply
并不会删除栈内的任何内容,但git stash pop
将栈顶工作状态出栈的同时也会删除栈顶的内容。
小结:
-
git stash 暂存当前工作状态,等恢复现场后继续工作
-
git stash list 查看所有暂存的工作状态
-
git stash pop 恢复工作状态,删除栈顶内容
-
git stash apply 恢复工作状态,不删除栈内内容
-
git stash drop 删除栈顶内容
2.4 远程仓库
在本章,你需要有一个GitHub账号,并且在GitHub上添加了一个远程仓库。远程仓库是指托管在互联网的版本库。
配置git
设置用户名和邮箱。
git config --global user.email "your_email@example.com" # --global表示全局设置
git config --global user.name "your_name"
查看配置。
git config -l
将SSH Key添加到GitHub。
ssh-keygen -t rsa -C "your_email@example.com" # 结果显示:Your public key has been saved in /root/.ssh/id_rsa.pub
cat /root/.ssh/id_rsa.pub # 查看公钥并将其复制,之后粘贴到GitHub网页上
在GitHub网页中,点击个人头像 → Settings → SSH and GPG keys → New SSH key,添加公钥。
克隆远程仓库(git clone)
git clone <url> #远程服务器的URL
当你克隆某个远程仓库后,默认情况下Git会自动设置本地master
分支跟踪 克隆的远程仓库的master
分支(或其它名字的默认分支),并且默认设置远程仓库在本地的别名是origin
。
实际上克隆命令是git clone <repo>
,表示克隆⼀个指定repo到本地,其指定repo可以是本地⽂件系统或者由HTTP或SSH指定的远程路径。
添加/删除远程仓库(git remote add/rm)
(1)添加远程仓库
实际就是给远程仓库服务器地址起一个本地的别名/简称(习惯命名为origin)。
将远程服务器地址<url>
映射为 本地对远程服务器的别名<shortname>
,命令格式如下:
git remote add <shortname> <url> #将<shortname>与<url>关联,以后就可以用<shortname>代替<url>
示例:
#进入GitHub远程仓库的网页,点击Code和SSH,查看SSH协议的<url>,例如git@github.com:nefu-ljw/ACM-Algorithm.git
git remote add origin git@github.com:.git
(2)删除远程仓库
git remote rm <shortname> #删除别名<shortname>及其对应的远程服务器地址
一旦使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。
推送远程仓库(git push)
将本地仓库的分支<branch>
推送到远程服务器<remote>
,命令格式如下:
git push <remote> <branch> # 这里的<remote>就是之前添加的远程服务器地址的别名<shortname>
如果是第一次将本地分支master
推送到远程服务器origin
,则使用-u
选项指定一个默认服务器:
git push -u origin master #之后会产生远程分支origin/master,并且本地分支master跟踪远程分支origin/master
如果当前分支与多个服务器存在跟踪关系,可以使用-u
选项指定一个默认服务器,以后就可以不加任何参数直接使用git push
。
当你和其他人在同一时间克隆,但他们先推送然后你再推送,那么你的推送会被拒绝,因为你要推送的本地分支落后于远程服务器的分支。你必须先抓取(fetch)他们的工作并将其合并(merge)进你的工作后才能推送。或者用-force
选项强行推送你的本地库,但是这样会使得远程服务器丢失其他人的变更,请慎重使用。
注:git push需要输入用户名和密码,输入密码时可能出现要求输入token的问题,可参考此文解决。
查看远程仓库(git remote -v/show)
如果想查看已经配置的远程仓库服务器,可以用git remote
列出已指定的每一个远程服务器的简写。
你也可以指定选项-v
,将会显示远程服务器使用的简写<shortname>
与其对应的<url>
。
git remote -v
运行命令后,将会显示可以进行抓取(fetch)和推送(push)的地址:
origin git@github.com:nefu-ljw/ACM-Algorithm.git (fetch)
origin git@github.com:nefu-ljw/ACM-Algorithm.git (push) (注:如果没有推送权限,则看不到push的地址)
如果你已经克隆了仓库,那么至少能看到origin
,这是Git给你克隆的远程服务器的默认别名。
如果想要查看某一远程仓库<remote>
的更多信息,可以用:
git remote show <remote>
- 1这个命令列出了当你在特定的分支上执行
git push
会自动地推送到哪一个远程分支。 它也同样地列出了哪些远程分支不在你的本地,哪些远程分支已经从服务器上移除了, 还有当你执行git pull
时哪些本地分支可以与它跟踪的远程分支自动合并。