Skip to content
索引

提交代码至远程仓库

本地代码初次提交至远程空仓库时需要运行git init命令,创建必要的.git文件即本地仓库,该文件默认是隐藏的,.git文件中存储本项目相关git信息,如后续添加的远程仓库地址,每次提交内容的说明也就是git commit等等信息

提交代码

origin是远程仓库的别名,github远程仓库的名称默认为origin

git push -ugit push --set-upstream的缩写,表格关联远程仓库

git add是将文件从工作区–>暂存区 git commit 是将文件从暂存区–>git本地仓库

sh
# 创建.git文件即本地仓库
git init   
# 添加远程仓库地址
git remote add origin https://git-repo-address.git  
# 保存项目内容至本地仓库
git add . 
# 本次提交的说明
git commit -m "commitText" 
# push时关联远程仓库
git push -u origin master 
# 创建.git文件即本地仓库
git init   
# 添加远程仓库地址
git remote add origin https://git-repo-address.git  
# 保存项目内容至本地仓库
git add . 
# 本次提交的说明
git commit -m "commitText" 
# push时关联远程仓库
git push -u origin master 

之后提交

sh
git add . 
git commit -m "commitText" 
# 多人开发的项目每次提交前应先pull拉取代码
# 其他开发者可能比你先提交代码,不拉取直接提交会覆盖他的代码,一般情况下git也会进行提示
git pull 
# 拉取后没有代码冲突(不同开发者修改了相同一处的代码)可以直接提交
git push 
git add . 
git commit -m "commitText" 
# 多人开发的项目每次提交前应先pull拉取代码
# 其他开发者可能比你先提交代码,不拉取直接提交会覆盖他的代码,一般情况下git也会进行提示
git pull 
# 拉取后没有代码冲突(不同开发者修改了相同一处的代码)可以直接提交
git push 

如果出现代码冲突问题(相同代码处有不同的修改),这时需要手动在项目中选择保存哪一部分代码,从而解决冲突,然后重新走一遍提交流程

git stash暂存代码

比如在dev分支开发功能,但功能代码还没写完,要去修复一个线上的bug,这时不适合commit,也不适合直接切换分支(直接切换分支会导致自动合并)

不提交的情况下切换分支

会出现以下报错

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

这时就需要使用stash命令, 将当前未提交的修改(即,工作区的修改和暂存区的修改)先暂时储藏起来,这样工作区干净了后,就可以切换到master分支,然后再创建一个fix分支。在完成线上bug的修复工作后,重新切换到dev分支

sh
git stash
git checkout master
git stash
git checkout master

修改完之后,回到开发分支,执行

sh
git checkout dev
# 查看储存的修改
git stash list
git checkout dev
# 查看储存的修改
git stash list

方法一

git stash apply stash@{index}表示取出指定储藏中的修改到工作区

git stash drop stash@{index}表示将指定index的储藏从储藏记录列表中删除

sh
# 单个存储
git stash apply
git stash drop
# 多个存储,示例,应用第一个存储
git stash apply stash@{0}
git stash drop stash@{0}
# 单个存储
git stash apply
git stash drop
# 多个存储,示例,应用第一个存储
git stash apply stash@{0}
git stash drop stash@{0}

方法二:

git stash pop可取出最近一次储藏的修改到工作区,并同时将该储藏从储藏记录列表中删除

git stash pop stash@{index}表示通过储藏列表的index取出指定储藏中的修改到工作区

sh
git stash pop
# 多个存储,示例,应用第一个存储
git stash pop stash@{0}
git stash pop
# 多个存储,示例,应用第一个存储
git stash pop stash@{0}

错误提交进行回退

1.没有git add时,用git checkout -- file

2.已经git add时,先git reset HEAD <file>回退到1.,再按1.操作

3.已经git commit时,用git reset回退版本

4.推送到远程库,GG?

合并commit

主要目的是将许多提交合并为几个更简洁明了的提交

一般有两种情况

  • 将当前分支不同的提交合并为一个。以便git历史记录看起来清晰并最好地反映已完成的任务
  • 在进行分支合并时进行压缩。比如,从主分支创建一个功能分支,用于某些功能开发,功能完成后,将功能分支合并到主分支中,这时,有可能希望将功能分支中完成的各种提交消息压缩为一个

使用交互式 git rebase 工具压缩 Git 提交

考虑以下 git log 摘录,它显示了我们对压缩感兴趣的 HEAD 的最后四个提交

sh
25c38c4 remove .class files
da66e6a Delete version.ini
f4e3f09 Delete .log
b0e6655 Delete .lock
da66e6a github git notes
25c38c4 remove .class files
da66e6a Delete version.ini
f4e3f09 Delete .log
b0e6655 Delete .lock
da66e6a github git notes

我们可以在日志中看到前四个提交消息,表示删除不同的不相关文件的操作。现在,我们将把这四个提交合并为一个

以下是使用交互式变基工具压缩最后 X 次提交的命令的语法

sh
git rebase -i HEAD~[X]`
git rebase -i HEAD~[X]`

因此,要压缩四个提交,我们将执行以下操作。

sh
$ git rebase -i HEAD~4
$ git rebase -i HEAD~4

发出此命令后,Git 将调用vim编辑器

sh
pick b0e6655 Delete .lock
pick f4e3f09 Delete .log 
pick da66e6a Delete version.ini
pick 25c38c4 remove .class files

# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
pick b0e6655 Delete .lock
pick f4e3f09 Delete .log 
pick da66e6a Delete version.ini
pick 25c38c4 remove .class files

# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

编辑器使用 pick 命令显示各种提交。它还显示有关可用命令的信息。我们将使用 squash(或 s)命令。

如下所示,我们将使用 pick 命令保留第一个提交,并将其余三个提交从 pick 更改为 s(用于壁球)命令。

sh
pick b0e6655 Delete .lock
s f4e3f09 Delete .log 
s da66e6a Delete version.ini
s 25c38c4 remove .class files

# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
...
pick b0e6655 Delete .lock
s f4e3f09 Delete .log 
s da66e6a Delete version.ini
s 25c38c4 remove .class files

# Rebase 652d2fe..25c38c4 onto 652d2fe (4 command(s))
#
...

标有 squash(或 s)的提交将合并到主提交即。标有 pick 的那个。

现在,我们将在编辑器中保存更改并退出。在此之后,rebase -i 工具将打开另一个编辑器以输入提交消息,如下所示:

sh
# This is a combination of 4 commits. The first commit's message is:

Delete .lock

# This is the 2nd commit message:

Delete .log 

# This is the 3rd commit message:

Delete version.ini

# This is the 4th commit message:

remove .class files

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Jan 3 16:39:23 2021 +0530
#
# interactive rebase in progress; onto 652d2fe
# Last commands done (4 commands done):
#    pick b0e6655 Delete .lock
#    s f4e3f09 Delete .log 
#    s da66e6a Delete version.ini
#    s 25c38c4 remove .class files
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '652d2fe'.
#
# Changes to be committed:
#       new file:   github-git-notes.txt
#
# This is a combination of 4 commits. The first commit's message is:

Delete .lock

# This is the 2nd commit message:

Delete .log 

# This is the 3rd commit message:

Delete version.ini

# This is the 4th commit message:

remove .class files

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Jan 3 16:39:23 2021 +0530
#
# interactive rebase in progress; onto 652d2fe
# Last commands done (4 commands done):
#    pick b0e6655 Delete .lock
#    s f4e3f09 Delete .log 
#    s da66e6a Delete version.ini
#    s 25c38c4 remove .class files
# No commands remaining.
# You are currently editing a commit while rebasing branch 'master' on '652d2fe'.
#
# Changes to be committed:
#       new file:   github-git-notes.txt
#

现在,我们将在第一条提交消息的顶部添加新的提交消息。

sh
Deleted irrelevant files

# This is a combination of 4 commits. The first commit's message is:

Delete .lock

# This is the 2nd commit message:

Delete .log
...
Deleted irrelevant files

# This is a combination of 4 commits. The first commit's message is:

Delete .lock

# This is the 2nd commit message:

Delete .log
...

保存并退出编辑器后,rebase -i 工具将打印以下消息。

sh
HEAD~2
Rebasing (2/2)


[detached HEAD caab6e8] Deleted irrelevant files
 Date: Sun Jan 3 16:39:23 2021 +0530
 1 file changed, 54 insertions(+)
 create mode 100644 github-git-notes.txt
Successfully rebased and updated refs/heads/master.
HEAD~2
Rebasing (2/2)


[detached HEAD caab6e8] Deleted irrelevant files
 Date: Sun Jan 3 16:39:23 2021 +0530
 1 file changed, 54 insertions(+)
 create mode 100644 github-git-notes.txt
Successfully rebased and updated refs/heads/master.

现在,我们将检查 git log 并查看 squashed 提交(即)单个提交消息而不是四个提交消息。

sh
$ git log --oneline
25c38c4 Deleted irrelevant files
da66e6a github git notes
...
$ git log --oneline
25c38c4 Deleted irrelevant files
da66e6a github git notes
...

使用 git merge -squash 压缩 Git 提交

以下是将分支与当前分支(通常是 main)合并并压缩源分支的提交的命令语法。

sh
git merge --squash <source_branch_name_to_squash>
git merge --squash <source_branch_name_to_squash>

我们现在将合并功能分支即。feature1 与 main 分支一起压缩。

首先,我们将切换到 master 分支。

sh
$ git checkout main
Switched to branch 'main'
$ git checkout main
Switched to branch 'main'

然后,我们将使用 squash 选项执行 git merge,如下所示。

sh
$ git merge --squash feature1
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
$ git merge --squash feature1
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

当我们使用 --squash 选项执行 merge 时,Git 不会像在正常合并中那样在目标分支中创建合并提交。相反,Git 接受源分支中的所有更改。feature1 并将其作为本地更改放入目标分支即 master 的工作副本中。

请参阅下文。

sh
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   config.ini
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   config.ini

在这里,文件 config.ini 在 feature1 分支中进行了更改。

现在,剩下的就是将更改提交到 main 分支,如下所示。

sh
$ git commit -am 'Merged and squashed the feature1 branch changes'
[main 573b923] Squashed and merged the feature1 branch
 1 file changed, 4 insertions(+)
$ git commit -am 'Merged and squashed the feature1 branch changes'
[main 573b923] Squashed and merged the feature1 branch
 1 file changed, 4 insertions(+)

因此,我们现在已将 feature1 分支中的更改合并到 main 分支,同时压缩了 feature1 分支的提交消息。我们现在在 main 分支中只有一条提交消息。

git rebase/变基

变基时有六个命令可用:

edit

如果您选择edit提交,则将有机会修改提交,这意味着您可以完全添加或更改提交。您还可以进行更多提交,然后再继续进行变基。这使您可以将大型提交拆分为较小的提交,或者删除在提交中所做的错误更改

exec

这使您可以对提交运行任意的Shell命令

pick/更改提交顺序

pick只是意味着包括提交。重新进行命令时,重新安排pick命令的顺序会更改提交的顺序。如果选择不包括提交,则应删除整行

示例操作,更换倒数第一次和倒数第二次的提交记录顺序

  1. git rebase -i HEAD~2 表示改变倒数第2次后的提交,会打开vim编辑器
  2. 把 第一行 和 第二行 交换顺序,移动到第一行 按dd,本行就被剪切,第二行就变成了第一行,接着按 p刚刚剪切的就成了第二行,快速交换顺序
  3. 接着 Esc,:wq 保存退出

reword/更改提交信息

该reword命令与相似pick,但是使用后,重新设置过程将暂停并为您提供更改提交消息的机会。提交所做的任何更改均不受影响

示例操作,更改第一行的提交信息

  1. git rebase -i HEAD~1
  2. i进入插入模式,Del删除第一行的pick,改为r
  3. 接着 Esc,:wq 保存退出
  4. 就可以修改第一行了的commit了,i进入插入模式,更改第一行commit
  5. 接着 Esc,:wq 保存退出

squash/合并提交

该命令使您可以将两个或多个提交合并为一个提交。提交被压缩到其上方的提交中。Git使您有机会编写描述这两个更改的新提交消息

示例操作,合并第一行和第二行的提交

  • git rebase - i HEAD~2
  • i进入插入模式,Del删除第二行的pick,改为s
  • 接着 Esc,:wq 保存退出
  • 就可以修改输入后的commit了,输入commit
  • 接着 Esc,:wq 保存退出

fixup/合并提交

类似squash,也是用于合并提交,但要合并的提交会丢弃其commit消息。提交仅合并到其上方的提交中,并且使用较早提交的commit消息来描述这两个更改

示例操作,合并第一行和第二行的提交

  • git rebase -i HEAD~2
  • i进入插入模式,Del删除第二行的pick,改为f
  • 接着 Esc,:wq 保存退出
  • git log打印会发现只有最新一次和倒数第二次的commit合并了,commit消息是倒数第二次的消息

git rebase --abort

控制台出现:fatal: It seems that there is already a rebase-merge directory, and I wonder if you are in the middle of another rebase. If that is the case, please try

使用该命令解决该问题,放弃之前的变基操作

用法一

场景:一个开发任务,需要三天完成,每天都提交一部分代码,直到第三天完成整个任务,这时候我们想合并第一天到第三天的commit提交记录,因为这才是一个完整的开发任务,从而使记录更简洁更易于他人

sh
# 指定一个commit的hash代码,合并当前到该hash之间的所有提交记录
git rebase -i commit的hash代码
# 指定一个commit的hash代码,合并当前到该hash之间的所有提交记录
git rebase -i commit的hash代码

commit添加emoji

在提交内容的前面增加emoji代码

bash
git commit -m '	:art: :zap: :racehorse: 此次提交的内容说明'
git commit -m '	:art: :zap: :racehorse: 此次提交的内容说明'

列表见下面的附录表格

emojiemoji代码commit 说明
🎨 (调色板):art:改进代码结构/代码格式
⚡ (闪电)🐎 (赛马):zap:“:racehorse:提升性能
🔥 (火焰):fire:移除代码或文件
🐛 (bug):bug:修复 bug
🚑 (急救车):ambulance:重要补丁
✨ (火花):sparkles:引入新功能
📝 (备忘录):memo:撰写文档
🚀 (火箭):rocket:部署功能
💄 (口红):lipstick:更新 UI 和样式文件
🎉 (庆祝):tada:初次提交
✅ (白色复选框):white_check_mark:增加测试
🔒 (锁):lock:修复安全问题
🍎 (苹果):apple:修复 macOS 下的问题
🐧 (企鹅):penguin:修复 Linux 下的问题
🏁 (旗帜):checked_flag:修复 Windows 下的问题
🔖 (书签):bookmark:发行/版本标签
🚨 (警车灯):rotating_light:移除 linter 警告
🚧 (施工):construction:工作进行中
💚 (绿心):green_heart:修复 CI 构建问题
⬇️ (下降箭头):arrow_down:降级依赖
⬆️ (上升箭头):arrow_up:升级依赖
👷 (工人):construction_worker:添加 CI 构建系统
📈 (上升趋势图):chart_with_upwards_trend:添加分析或跟踪代码
🔨 (锤子):hammer:重大重构
➖ (减号):heavy_minus_sign:减少一个依赖
🐳 (鲸鱼):whale:Docker 相关工作
➕ (加号):heavy_plug_sign:增加一个依赖
🔧 (扳手):wrench:修改配置文件
🌐 (地球):globe_with_meridians:国际化与本地化
✏️ (铅笔):pencil2:修复 typo

git reset --soft

语法:git reset --soft 版本号

作用:用于版本的回退,只进行对commit操作的回退,不影响工作区的文件

应用场景:在提交代码之后,又在工作区添加了东西,这时候突然发现,上一次的commit有错误的文件,需要重新修改,但是添加的东西又不想丢失,而且又想修改上一次的提交,这时候可进行git reset --soft版本号

git log

git log命令用于显示历史提交记录

按住上下键列表滚动,按q退出log模式

sh
git log
git log

参数

  • --oneline 打印在一行, 显示的是历史记录的简洁版本
  • --graph 查看历史中什么时候出现了分支、合并
  • git log --author=name 只想查找指定用户的提交日志

定制git log格式

个人使用的自定义log命令

sh
git log --pretty=format:"* %Cblue%h%Creset - (%Cgreen%ar%Creset) %s -- %Cblue%an"
git log --pretty=format:"* %Cblue%h%Creset - (%Cgreen%ar%Creset) %s -- %Cblue%an"

其它一些自定义log命令参考

sh
git log --pretty=format:"%an, %ar : %s"
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
git log --pretty=format:"  %an : %Cgreen%ar , %Cblue%s% "
git log --pretty=format:"%an, %ar : %s"
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
git log --pretty=format:"  %an : %Cgreen%ar , %Cblue%s% "
选项说明
%H提交对象(commit)的完整哈希字串
%h提交对象的简短哈希字串
%T树对象(tree)的完整哈希字串
%t树对象的简短哈希字串
%P父对象(parent)的完整哈希字串
%p父对象的简短哈希字串
%an作者(author)的名字
%ae作者的电子邮件地址
%ad作者修订日期(可以用 -date= 选项定制格式)
%ar作者修订日期,按多久以前的方式显示
%cn提交者(committer)的名字
%ce提交者的电子邮件地址
%cd提交日期
%cr提交日期,按多久以前的方式显示
%s提交说明
%Creset表示重置颜色,不受之前的颜色
%Cred红色
%Cgreen绿色
%Cblue蓝色

作者(author)和 提交者(committer)区别 : 作者指的是实际作出修改的人,提交者指的是最后将此修改提交到仓库的人

命令别名

自定义的命令无疑是很长的,基本上只能复制粘贴地进行使用,所以使用命令别名来更方便地使用

如以下命令设置别名为git lg ,之后直接输入git lg即可

sh
git config --global alias.lg "log --pretty=format:'* %Cblue%h%Creset - (%Cgreen%ar%Creset) %s -- %Cblue%an'"
git config --global alias.lg "log --pretty=format:'* %Cblue%h%Creset - (%Cgreen%ar%Creset) %s -- %Cblue%an'"

git blame/查看指定文件的修改记录

语法:

  • sh
    git blame <file>
    
    git blame <file>
    
  • git blame 命令是以列表形式显示修改记录,如下实例:

  • sh
    git blame README 
    ^d2097aa (tianqixin 2020-08-25 14:59:25 +0800 1) # Runoob Git 测试
    db9315b0 (runoob    2020-08-25 16:00:23 +0800 2) # 菜鸟教程 
    
    git blame README 
    ^d2097aa (tianqixin 2020-08-25 14:59:25 +0800 1) # Runoob Git 测试
    db9315b0 (runoob    2020-08-25 16:00:23 +0800 2) # 菜鸟教程 
    

Released under the MIT License.