git 工作区
工作区:我们直接编辑的地方,记事本打开的文本等,肉眼可见,直接操作。
暂存区:数据暂时存放的区域,可在工作区和版本库之间进行数据的友好交流。
本地仓库:存放已经提交的数据
远程仓库:存放本地仓库push的数据
撤回命令
这里重点说一下撤销命令,可以分为四个阶段:
- 撤销工作区的未暂存修改(未执行 git add)
# 撤销单个文件的修改
git restore <file>
# 撤销所有未暂存的修改
git restore .
- 撤销暂存区的已暂存修改(已执行 git add)
# 将单个文件移出暂存区(保留工作区修改)
git restore --staged <file> # 推荐(Git 2.23+)
# 将所有文件移出暂存区
git restore --staged . # 谨慎使用!会清空暂存区
撤销本地仓库的提交(已执行 git commit)
# 撤销最近一次提交,保留修改到工作区 git reset HEAD~1 # 默认 --mixed 模式 # 彻底删除最近一次提交(丢弃所有修改) git reset --hard HEAD~1 # 慎用!会彻底丢弃提交和修改 # 撤销最近一次提交,保留修改到暂存区 git reset --soft HEAD~1 # 修改上一次提交的 message 或内容 git commit --amend # 修改提交信息或追加新修改
撤销远程仓库的提交(已执行 git push)
# 生成一个反向提交,抵消之前的修改
git revert <commit-hash>
stash命令
背景:在一个分支开发新功能,还没开发完毕,做到一半时有反馈紧急bug需要处理,但是新功能开发了一半又不想提交。分支有改变时不提交又不能切换分支
# message为添加的一些注释
git stash save 'message...'
它会保存当前工作进度,会把暂存区和工作区的改动保存到一个未完结变更的堆栈中;执行完这个命令后,在运行 git status 命令,就会发现当前是一个干净的工作区,没有任何改动。
# 恢复的时候使用 git stash list 查看有没有已经 stash 的记录
# 然后使用git stash apply n 回到指定版本
# n为stash list结果里面的需要0、1、2、3
# 查看有无用的 list,可以先使用 git stash drop n 删除,直到 list 为空
clone、pull、fetch命令
git clone:将远程仓库完整复制到本地,适合第一次从远程获取项目。
pull = fetch + merge
git fetch:拉取远程仓库的最新提交、分支和标签,但不会修改本地工作区,所以fetch后看不到文件变化
# 拉取远程所有分支的最新信息
git fetch origin
# 拉取特定分支的更新
git fetch origin main
如果需要看到变化,需要手动合并到本地分支:
git merge origin/main # 或使用 git pull(等同于 fetch + merge)
config相关命令
查看配置信息
- 查看系统config
git config --system --list
- 查看当前用户(global)配置
git config --global --list
- 查看当前仓库配置信息
git config -- local --list
设置/修改配置信息
设置用户名:
git config --global user.name "github用户名"
设置邮箱
git config --global user.email "github注册邮箱"
查看提交记录+commit相关操作
查看指定文件的历史提交记录
git log -- <file> //主要,这个文件要在当前目录才能直接输文件名,否则要给出路径
查看每次提交的内容差异
git log -p -2 -- <file>
参数:-p 表示每次提交的内容差异,-2 则表示显示最近的两次更新。
说明:该选项除了显示基本信息之外,还在附带了每次 commit 的变化。
根据哈希值查看修改代码细节
git show 哈希值
git show 哈希值 文件名 //具体某个文件的变化
根据分支或用户查看提交信息
git log 分支名
git log --authot='用户名'
//这两个命令可以通过 | xargs 与 git show搭配用
单词层面上的对比
git log --word-diff -- <file>
参数:—word-diff 表示获取单词层面上的对比。
说明:进行单词层面的对比常常是没什么用的。不过当你需要在书籍、论文这种很大的文本文件上进行对比的时候,这个功能就显出用武之地了。
提示:新增加的单词被 {+ +} 括起来,被删除的单词被 [- -] 括起来。
图形化查看提交历史
gitk -- <file>
说明:随 Git 一同发布的 gitk 就是这样一种工具。它是用 Tcl/Tk 写成的,基本上相当于 git log 命令的可视化版本,凡是
git log 可以用的选项也都能用在 gitk 上。
**
gitk中文乱码问题
**
解决办法:
打开git的配置文件(根据自己安装的git目录,此处为安装在D盘):D:\Program Files\Git\etc\gitconfig
在文件内追加以下内容:
[gui]
encoding = utf-8
提取git中某个文件的所有版本并按顺序命名
git log --follow --pretty=format:%H 文件名 | xargs -I{} sh -c 'git show {}:文件名 > 文件名.{}'
文件名需要进行替换,不可直接输入 文件名 三个字
如果出现
Did you menan ‘哈希值:路径’ aka ‘哈希值:路径’
字眼的错误
给第二个文件名添加 ./
git将远程分支按分支名在本地建立文件夹
git branch -r | xargs -d/ -n1 | grep -v 'origin' | xargs -I{} sh -c 'mkdir "C:\Users\76585\Desktop\try\{}" '
命令分线见 博客—Linux Shell命令总结
撤回git commit 操作
写完代码后,我们一般这样
git add .
git commit -m “msg”
执行完commit后,想撤回commit,怎么办?
- 撤回操作
git reset —soft HEAD^
(ps:如果控制台出现More?,则将命令改成 git reset —soft HEAD^^即可)
这样就成功的撤销了你的commit
注意,仅仅是撤回commit操作,您写的代码仍然保留。
说一下个人理解:
HEAD^的意思是上一个版本,也可以写成HEAD~1
如果你进行了2次commit,想都撤回,可以使用HEAD~2
- 参数:
—mixed
意思是:不删除工作空间改动代码,撤销commit,并且撤销git add . 操作
这个为默认参数,git reset —mixed HEAD^ 和 git reset HEAD^ 效果是一样的。
—soft
不删除工作空间改动代码,撤销commit,不撤销git add .
—hard
删除工作空间改动代码,撤销commit,撤销git add .
注意完成这个操作后,就恢复到了上一次的commit状态。
- 修改注释
顺便说一下,如果commit注释写错了,只是想改一下注释,只需要:
git commit —amend
此时会进入默认vim编辑器,修改注释完毕后保存就好了。
比较两个分支的commit
比如我们有 2 个分支:master, dev,现在想查看这两个 branch 的区别,有以下几种方式:
- 查看 dev 有,而 master 中没有的
git log dev ^master
查看 master 中有,而 dev 中没有的内容:
git log master ^dev
查看 dev 中比 master 中多提交了哪些内容
git log master..dev
不管谁提交的多谁提交的少,单纯想知道有什么不一样
git log dev...master
- 在上述情况下,再显示出每个提交是在哪个分支上:
git log --left-right dev...master
修改提交的信息
假设你想修改当前分支的所有 commit message,可以通过以下方式:
git rebase -i --root
你将看到一个编辑器窗口,列出当前分支的所有提交,格式类似于:
pick a1b2c3d commit message 1
pick b2c3d4e commit message 2
pick c3d4e5f commit message 3
你需要将每个 pick 改为 reword,例如:
reword a1b2c3d commit message 1
reword b2c3d4e commit message 2
reword c3d4e5f commit message 3
然后保存并退出。这个时候只需要修改
接着去修改每个message
这里的编辑器,有可能是vim,也有可能是nano。
nano直接编辑即可,通过Ctrl + O(保存)然后按下回车键来确认保存文件,接着按下Ctrl + X来关闭nano编辑器
分支操作
分支的使用
mster代表主分支,最终的代码都整合到这里面去,我们可以看下
这里只有一个主分支master。
有一种情况就是,一个项目多人开发,我的任务需要开发一个功能,我没办法短时间内就开发测试等等一系列完成。所以我可以新建一个分支,然后把每次完成的代码都上传到这个分支里面去,最后等到所有操作都完成后,我再把这个分支整合到master中去。下面看步骤
1.首先查看当前分支
git branch -a
-a代表查看本地和远程的分支,此时我们看到都只有一个master分支
2.新建分支dev
git checkout -b dev
执行该命令,会在本地创建一个新分支。该分支是从当前分支上生成的,所有内容和当前分支一样。
-b代表同时切换到dev分支下面去,这时你可以再去查看分支
3.然后我们重新写一个b.js文件,再执行add,commit,最后push
git add b.js
git commit -m "dev"
git push origin dev
注意push时要到dev分支
成功后我们去coding看已经有了dev,并且dev下有b.js,而master没有b.js
master:
我们可以再去看看分支情况,
git branch -a
此时已经有了两个分支,且当前位于dev分之下
切换分支可以用 git checkout [branch-name]
将远程git仓库里的指定分支拉取到本地(本地不存在的分支)
git checkout -b
上述命令虽然能生成新分支,但是会复制当前分支。但有时从远程仓库拉取分支,我只想要远程那个分支,不想先复制别的,这样拉下来会有冲突。
方法如下:
git checkout -b 本地分支名 origin/远程分支名
这个将会自动创建一个新的本地分支,并与指定的远程分支关联起来。
如果出现提示:
fatal: Cannot update paths and switch to branch 'dev2' at the same time.
Did you intend to checkout 'origin/dev2' which can not be resolved as commit?
或者:
fatal: 'origin/xlh' is not a commit and a branch 'xlh' cannot be created from it
git remote发现远程仓库的新分支没有显示出来,git fetch就好
表示拉取不成功或远程仓库信息没有更新。我们需要先执行
git fetch
然后再执行
git checkout -b 本地分支名 origin/远程分支名
删除分支
查看分支
git branch -a //远程的是红色
删除本地分支
git branch -d <BranchName>
删除远程分支
git push origin --delete <BranchName>
整合分支
当我们在dev下折腾完成后,最终要整合到master中去,看步骤
1.切换本地分支到master
git checkout master
2.将远程仓库的最新代码pull下来!!因为期间其他人可能已经提交代码到远程master了,所以你首先得更新下自己本地的master代码
git pull origin master
假如有改动过,那么执行后会显示改动的信息
3.然后再把本地的dev代码整合到master,输入
git merge dev
merge整合操作,把dev整合到当前分之下(当前分支为master)。会提示增加了东西
4.由于当前的东西已经在本地仓库里面了,所以最后我们再执行push,到远程仓库的master
git push origin master
成功后你可看到,master下已经有b.js文件了
本地从远程仓库拉取代码,只在某分支开发
远程仓库有master,dev1两个分支。本地用git clone拉取代码,git branch -a
查看,本地只有一个分支。此时用git checkout dev1
切换到dev1分支。代码和远程仓库一致。可以用git log
来确认是否是该分支(因为git log 只能看到当前分支的提交记录)
合并分支—git merge应用的三种情况
- “快进”(无冲突)
合并dev和master
由于当前 master 分支所指向的提交是你当前提交(dev的提交)的直接上游,所以 Git 只是简单的将 master 指针向前移动。 换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。合并结果如下:
- 非“快进”,修改不同文件。(无冲突)
在 master 分支和 dev 分支的公共祖先 B2 后,master 和 dev 的提交是对不同文件或者同一文件的不同部分进行了修改,Git 可以合并它们。(比如说原来有 test-1 和 test-2 两个文件,B4修改的是 test-1 文件,而B3修改的是 test-2 文件,然后合并两个分支。)
合并是成功的。
- 非“快进”,修改相同文件。(有冲突)
在 master 分支和 dev 分支的公共祖先 B2 后,master 和 dev 的提交是对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。(比如说原来有 test-1 和 test-2 两个文件,B4修改的是 test-1 文件,而B3修改的也是 test-1 文件的同一部分,然后合并两个分支。)
合并是失败的。
此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。
分支改名
- 修改本地分支名
git branch -m oldBranchName newBranchName
git 常用操作
git pull 与 git push 详解
1.git remote
git remote add origin url //这里面的origin 是给远程仓库起名字,不是给本地仓库!
2.git pull
git pull 其实就是 git fetch 和 git merge FETCH_HEAD 的简写。 命令格式如下:
git pull <远程主机名> <远程分支名>:<本地分支名>
将远程主机 origin 的 master 分支拉取过来,与本地的 brantest 分支合并。
git pull origin master:brantest
如果远程分支是与当前分支合并,则冒号后面的部分可以省略。
git pull origin master
3.git push
git push <远程主机名> <本地分支名>:<远程分支名>
如果本地分支名与远程分支名相同,则可以省略冒号:
git push <远程主机名> <本地分支名>
实例:
以下命令将本地的 master 分支推送到 origin 主机的 master 分支。
git push origin master
相等于:
git push origin master:master
如果本地版本与远程版本有差异,但又要强制推送可以使用 --force 参数:
git push --force origin master
删除主机的分支可以使用 --delete 参数,以下命令表示删除 origin 主机的 master 分支:
git push origin --delete master
将本地代码上传到远程仓库
1.(电脑里得先下载git)登录coding,新建一个仓库,点击代码浏览可以看到
2.在本地新建一个文件夹,作为项目根目录,再此启动 Git Bash ,进入目录,并输入
git init
3.将本地仓库和我们在coding上创建的远程仓库对接起来,输入
git remote add *yourname* *git_url* //不用输这条,输下面那条
add 后面输入你的仓库名字,自定义。git_url代表你的git地址,这里我命名为origin
git remote add origin *url* //这条指令是上面的详细版,输入这个就好。
(这里可能会出现叫你设置邮箱,和姓名,跟着提示设置就行了,或者可以选择以SSH公钥进行连接,不过得先去配置公钥)
回车成功后可以输入
git remote -v
4.为了我们的代码是最新的状态 和 提交时不会产生冲突,我们先执行下pull操作,将远程仓库最新代码拉到我们本地来,输入
git pull origin master
(origin就是我们上面设置的仓库名,master代表主分支,你可以把分支理解为一块区域,我们最终编写完成的代码都要整合到master分支里面去。然后,我们还可创建一些其他分支,去保存我们正在编写中,或者尚未测试的代码。)
执行完后,你可以查看目录下的文件,这时我们本地的文件就和远程仓库里面master分支里的文件一样了。
5.接下来我们来模拟写代码并上传到远程仓库去。
我们新建一个 a.js文件,并编辑一些内容进去。首先将a文件添加到暂存区
git add a.js //(add后面可以带多个文件名字,用空格隔开;或者输入 . 代表全部)
//然后再提交到本地仓库中去
git commit -m "first commit"
//然后我们需要把它push到远程仓库中去。输入
git push origin master //push到origin的master主分支里面,成功后会显示提示消息
查看远程仓库的情况
查看当前配置有哪些远程仓库
git remote
本地与远程仓库的取消
git remote remove “仓库名”
可以同时关联多个仓库,名字起的不一样就好,不一定非要用origin。但是要注意的是,git pull 和 git push指定的仓库名字也要改变。不然容易出问题。
回退到某版本
git reset --hard 139dcfaa558e3276b30b6b2e5cbbb9c00bbdca96
//后面的是git提交的历史版本号,上git上面找到复制下来就行
回退到某版本,且放弃之前的记录
git reset --hard回退之后,如果直接push会出错,因为我们本地库HEAD指向的版本比远程库的要旧,所以我们要用“git push -f”强制推上去
将现有代码保存带其它仓库
- git remote add neworigin “url”
- git push -u neworigin “分支名”
- 如果第二条命令不行就:git push -u neworigin “分支名” : “分支名”
生成新的ssh密钥
我们在重装系统后,如果要使用ssh来拉去代码,就需要生成密钥。
原文链接
1.打开git Bash。输入 ssh-keygen -t ed25519 -C "your_email@example.com"
;email替换为github的email(其他eamil没有尝试过)
2.后面一直回车就好,详细的去看原链接。需要注意的是不要更改密钥文件名字,否则会出问题。因为更改后,执行完后面的操作一直出问题。使用ssh -vT git@github.com
命令发现它一直在寻找带有id_rsa_字段的文件,擅自改了名字当然找不到,这个问题如何解决目前还没有找到方法。
3.eval "$(ssh-agent -s)"
//确保 ssh-agent 正在运行
4.ssh-add ~/.ssh/id_ed25519
//将 SSH 私钥添加到 ssh-agent。
5.将后缀为.pub的文件(公钥)添加到 GitHub 上的帐户
git push之前忘记了git pull,但是已经commit
背景:公司和家里面各有一台电脑。公司的电脑忘记了pull,对文件进行修改后,push无法成功。pull也被拒绝。如果直接回退,之前的记录就没了。而我想保留修改,因为也是有用的东西。
解决办法:
git stash //保存本地快照
git reset --hard "hash_value" //通过git log查看离的最近的没有发生冲突的提交记录,把哈希值找到,再回退
git pull origin hexo:hexo //hexo是博客的分支
git stash pop //把之前本地的修改重新补上
git bash扩展命令
原链接
总共有三个思路:
1.借助winpty调用cmd可以使用的命令
winpty 是一种提供与 cmd 通信的软件包,详情请参考 https://github.com/rprichard/winpty
git bash 命令行内没有 tree 命令而 cmd 命令行却有 tree 命令.
只不过 cmd 命令中的 tree 命令实际上是 tree.com 并不是 tree.exe 文件.
(tree 命令是以树状结构显示文件目录的一种命令,查看目录结构层次非常直观.)
`winpty tree.com` 效果等价于 `cmd` 内直接执行 `tree.com` 命令,瞬间解决了中文乱码问题
2.gunWin填补(用的最多)
绝大多数命令可以从这里找到,有的是可执行程序,有的是源码,需要先编译。
访问该网址
3.工具—Babun
4.工具—gitforwindows
扩展实例
安装make命令
- 前往该网址,下载 make-4.1-2-without-guile-w32-bin.zip,并解压zip文件
- 将解压内容(bin,lib等文件夹)放到git-bash安装路径的 mingw64文件夹 Git\mingw64\ (重复文件不要覆盖)
安装wget
- 前往该网址,下载最新的wget可执行文件(下载zip文件,包含document;或者直接下载exe文件)
- 得到wget.exe(如果可执行文件名称是wget64.exe,将其重命名为wget.exe)
- 将 wget.exe 移动到你的git-bash安装路径的bin文件夹中 Git\mingw64\bin\
安装sshpass
- 从网址下载1.05版本
- windows编译需要安装Cygwin编译器,如果安装的是MinGW,那么后面make会出错。win10 安装Cygwin。关键就是把编译c语言的相关东西装好。
- 进入sshpass源码,打开git bash。 ./configure
- make && make install
- 把编译好的exe程序放到:C:\Software\git\usr\bin;如果报缺少cygwin.dll这种信息,用everything搜索这个,然后放到这个目录
- 把上面的路径放到环境变量
git bash安装zip
git bash有些话可能没法执行zip命令
1.打开https://sourceforge.net/projects/gnuwin32/files/
2.2.找到zip和bzip2,由于zip依赖bzip2.dll,下载zip-3.0-bin.zip和bzip2-1.0.5-bin.zip,解压后,复制zip-3.0-bin的bin目录下的zip.exe 和bzip2-1.0.5-bin的bin目录下的bzip2.dll到 git/usr/bin/
放置的目录不能放错,一开始放到了git/bin/目录下,结果不行。
git 所遇问题
git代理
git代理一般分为两种:http和ssh
- http
仅为github.com设置socks5代理(推荐这种方式, 公司内网就不用设代理了, 多此一举):
git config —global http.https://github.com.proxy socks5://127.0.0.1:1086
其中1086是socks5的监听端口, 这个可以配置的, 每个人不同, 在macOS上一般为1086.
设置完成后, ~/.gitconfig文件中会增加以下条目:[http "https://github.com"] proxy = socks5://127.0.0.1:1086
- ssh
需要修改~/.ssh/config文件, 没有的话新建一个. 同样仅为github.com设置代理:Host github.com User git ProxyCommand nc -v -x 127.0.0.1:1086 %h %p
如果是在Windows下, 则需要个性%home%.ssh\config, 其中内容类似于:
Host github.com
User git
ProxyCommand connect -S 127.0.0.1:1086 %h %p
这里-S表示使用socks5代理, 如果是http代理则为-H. connect工具git自带, 在\mingw64\bin\下面.
当时我换了个梯子,导致无法使用ssh拉取代码。一开始以为是网络问题,后面发现是新梯子端口不对。把windows在用户目录下的.ssh目录里面的端口改好就可以了,本人电脑的配置如下:
Host github.com
HostName ssh.github.com
Port 443
ProxyCommand connect -S 127.0.0.1:7890 %h %p
Host github.com
User git
ProxyCommand connect -H 127.0.0.1:7890 %h %p
ssh Connection refused
ssh: connect to host github.com port 22: Connection refused
这个问题其实经常遇到,可以试下几个方法:
方法1:使用GitHub的443端口
在config 在目录~/.ssh/下,把端口指向443
修改为:
Host github.com
Hostname ssh.github.com
Port 443
原理是:默认情况下,SSH使用端口22来连接远程服务器。但是,一些网络防火墙或公司网络策略可能会阻止对端口22的访问。这会导致在使用git push等操作时出现连接关闭的错误。
端口443是用于HTTPS的标准端口,几乎所有的网络都允许通过这个端口进行通信。将SSH连接的端口改为443,可以绕过防火墙的限制,因为防火墙通常不会阻止443端口的通信。
GitHub为了应对这种情况,提供了一个可以通过端口443连接的SSH服务。通过将配置文件中的Port设置为443并将Hostname设置为ssh.github.com,你可以使用这个服务来进行SSH连接。
方法二:使用代理
具体配置见上面的 git代理
方法三:修改仓库的地址
仓库从ssh的地址修改为https的,这个方法有时候也可能不行。
git remote //查看地址
git remote remove origin //移除名为origin的地址(一般默认是这个命名)
git remote add origin https://xxxx
两台设备之前同步出问题
背景:
两台设备,共用同一个git仓库。设备a之前做了修改,但是忘记了提交。设备b一直在修改和提交。
我目前想在设备a上面push,失败:
To github.com:gaofeng-lin/gaofeng-lin.github.io.git
! [rejected] hexo -> hexo (non-fast-forward)
error: failed to push some refs to ‘github.com:gaofeng-lin/gaofeng-lin.github.io.git’
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push —help’ for details.
拉取也失败:
From github.com:gaofeng-lin/gaofeng-lin.github.io
- branch hexo -> FETCH_HEAD
735387a4..943f2d3b hexo -> origin/hexo
error: Your local changes to the following files would be overwritten by merge:
Please commit your changes or stash them before you merge.source/_posts/other/零散知识.md
解决办法:
处理设备a的本地未提交修改
# 方案1:提交本地修改(推荐) git add source/_posts/other/零散知识.md # 只暂存特定文件 git commit -m "保存设备a的修改" # 提交说明 # 方案2:临时暂存修改(后续需要恢复) git stash save "设备a的临时修改" # 暂存所有未提交内容
获取远程代码
git fetch origin # 获取远程分支信息 git pull origin hexo # 合并远程hexo分支到本地
处理合并的冲突
打开冲突文件查看<<<<<<<和>>>>>>>标记 手动保留合理修改后删除标记 执行 git add <冲突文件> 标记解决 继续 git commit -m "解决合并冲突"
git push重新提交