git 使用

  • 查看和修改用户名以及邮箱:
git config user.name
git config user.email
  • 设置/更改用户名和邮箱,有先后顺序:
git config --global user.name "your name"
git config --global user.email "your email"
  • 开启/关闭颜色
    git config --global color.ui true

  • 换行符操作

Linux是0x0A(LF),win是0x0D0A(CRLF)
AutoCRLF
1、提交时转换为LF,检出时转换为CRLF git config --global core.autocrlf true
2、提交时转换为LF,检出时不转换 git config --global core.autocrlf input
3、提交检出均不转换 git config --global core.autocrlf false

SafeCRLF
1、拒绝提交包含混合换行符的文件 git config --global core.safecrlf true
2、允许提交包含混合换行符的文件 git config --global core.safecrlf false
3、提交包含混合换行符的文件时给出警告 git config --global core.safecrlf warn

  • 代理设置

全局代理设置

git config --global http.proxy http://127.0.0.1:1080
git config --global https.proxy https://127.0.0.1:1080

只对github代理设置

git config --global http.https://github.com.proxy https://127.0.0.1:1080
git config --global https.https://github.com.proxy https://127.0.0.1:1080

**注意:**以上两点都是对https协议进行代理设置,也就是仅对git clone https://www.github.com/xxxx/xxxx.git这种命令有效。对于SSH协议,也就是git clone git@github.com:xxxxxx/xxxxxx.git这种,依旧是无效的。

sock5代理设置,只对GitHub进行代理

git config --global http.https://github.com.proxy socks5://127.0.0.1:1089
git config --global https.https://github.com.proxy socks5://127.0.0.1:1089

取消代理

git config --global --unset http.proxy
git config --global --unset https.proxy

查看已有配置

git config --global -l

** 代理文件的位置**

[09:19:05@]$cat ~/.gitconfig 
[user]
	email = ~@163.com
	name = youname

[http "https://github.com"]
  proxy = socks5://127.0.0.1:1089
  • 初始化一个Git仓库,使用git init命令:
git init
Initialized empty Git repository in /Users/michael/learngit/.git/
  • 使用命令git add <file>,注意,可反复多次使用,添加多个文件,
  1. git add -A 提交所有变化
  2. git add -u 提交被修改(modified)和被删除(deleted)文件,不包括新文件(new)
  3. git add . 提交新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件

git add readme.txt

  • 无法将文件夹下的某些文件添加进 Git 进行版本控制
发现原来是子文件夹下面含有 .git 文件夹,因此导致该子文件夹无法被 Git 跟踪,可以通过以下方法解决:
git rm --cached directory
git add directory
注:directory为子文件夹的路径。
  • 使用命令git commit
    git commit -s 在vim中添加提交信息(很实用)
    git commit -amend 最近提交的commitid中追加提交 (很实用,尤其是往远程仓库提交时,提交上去只有一个commit id ,管理者可以一目了然的看到提交)
    git commit -C hard -a --amend 追加到hard,不参数新的提交记录
$ git commit -m "add 3 files."
-m后面输入的是本次提交的说明
git commit -m "提交说明" -a //这是一个偷懒的命令,相当于 git add .; git commit;
  • git log命令显示从最近到最远的提交日志,
    git log --stat 查看每条log提交对应的修改(比较常用)
    git log --graph命令可以看到分支合并图
    git log -p 文件名 可查看该文件以前每一次push的修改内容
    git log - p -1 文件名 只查看该文件当前这一次的push内容
    git show commit-id filename 只看某次提交中的某个文件变化
    git log --grep 关键字 仅显示含指定关键字的提交
    git log -S 关键字 仅显示添加或移除了某个关键字的提交
    git log --committer zhubo(作者) 仅显示指定提交者相关的提交,没有具体提交内容
    git log --author zhubo(作者) 仅显示指定作者相关的提交,有具体提交内容
$ git log
commit 3628164fb26d48395383f8f31179f24e0882e1e0
Author: Michael Liao <askxuefeng@gmail.com>
Date:  Tue Aug 20 15:11:49 2013 +0800

可以试试加上--pretty=oneline参数嫌输出信息太多,
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
  • 命令git reflog用来记录你的每一次命令
$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file
  • Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_idgit reset --soft commit_id

说明:
--hard会毁掉提交的暂存区,丢弃改动代码就不要用
--soft 会回到commit_id,对应的提交会保存到暂存区,推荐使用这个

$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed
HEAD^:当前版本的上一版本,上上一个版本就是HEAD^^,

$ git reset --hard 3628164
HEAD is now at 3628164 append GPL

1、用git log可以查看提交历史,以便确定要回退到哪个版本
2、用git reflog查看命令历史,以便确定要回到未来的哪个版本
  • 命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区:
  • git revert 是生成一个新的提交来撤销某次提交,此次提交之前的commit都会被保留
$ git reset HEAD readme.txt
Unstaged changes after reset:
M      readme.txt
  • git status查看一下状态:
$ git status
\# On branch master# Changes to be committed:
\#  (use "git reset HEAD <file>..." to unstage)
\#
\#      new file:  LICENSE#      modified:  readme.txt
\#
  • 用 git diff HEAD – 命令可以查看工作区和版本库里面最新版本的区别:

Git diff branch1 branch2 --stat //显示出所有有差异的文件列表
Git diff branch1 branch2 文件名(带路径) //显示指定文件的详细差异
Git diff branch1 branch2 //显示出所有有差异的文件的详细差异

git diff -cached 要看已经暂存起来的文件和上次提交时的快照之间的差异

$ git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index 76d770f..a9c5755 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
 Git is a distributed version control system.
 Git is free software distributed under the GPL.
 Git has a mutable index called stage.
-Git tracks changes.
+Git tracks changes of files.
  • git show 可以看到项目的一些状态
    git show commitid 可以查看对应更改
  • git checkout – file可以丢弃工作区的修改(本地删除,从版本库还原)
$ git checkout -- readme.txt
  • git checkout branch就变成了“切换到另一个分支”的命令
  • 用命令git rm 要从版本库中删除该文件, 并且git commit
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d17efd8] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt
  • 查看分支:git branch命令查看当前分支, git branch命令会列出所有分支,当前分支前面会标一个*号
    查看所有分支git branch -a包括远程的分支
$ git branch
* dev
  master
  • 创建分支:git branch <name>
  • 切换分支:git checkout <name>
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
  • 创建+切换分支:git checkout -b <name>,命令加上-b参数表示创建并切换,相当于上面两条命令:
$ git checkout -b dev
Switched to a new branch 'dev'
  • 新建分支并切换到远程分支
git checkout -b 本地分支名 origin/远程分支名
  • 合并某分支到当前分支:git merge <name>, 注意--no-ff参数 表示禁用Fast forward
$ git merge dev
Updating d17efd8..fec145a
Fast-forward//快捷模式,也就是直接把master指向dev
readme.txt |    1 +
1 file changed, 1 insertion(+)

加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并
$ git merge --no-ff -m "merge with no-ff" dev
Merge made by the 'recursive' strategy.
readme.txt |    1 +
1 file changed, 1 insertion(+)

git merge --squash dev 将dev分支上的多个commit合并成一个,放在当前分支上,原来的commit历史则没有拿过来,当前修改没问题再做一次commit提交
–squash选项的含义是:本地文件内容与不使用该选项的合并结果相同,但是不提交、不移动HEAD,因此需要一条额外的commit命令。

  • 删除分支:git branch -d <name> ,如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除
$ git branch -d dev
Deleted branch dev (was fec145a).
  • 当前工作现场“储藏”起来git stash
$ git stash
Saved working directory and index state WIP on dev: 6224937 add merge
HEAD is now at 6224937 add merge
  • 查看储藏:git stash list命令
$ git stash list
stash@{0}: WIP on dev: 6224937 add merge
  • 恢复储藏现场: git stash apply, stash内容并不删除,删除储藏现场: git stash drop;或 git stash pop 恢复的同时把stash内容也删了
$ git stash pop
# On branch dev
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   hello.py
#
# 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:   readme.txt
#
Dropped refs/stash@{0} (f624f8e5f082f2df2bed8a4e09c12fd2943bdd40)
  • 在github建立仓库

1、登陆github.com
2、Create New Repository

  • github建立仓库后
echo "# my_vimrc" >> README.md
git initgit add README.md
git commit -m "first commit"
//origin 远程仓库的简单名,可以用git remote查看
git remote add origin https://github.com/90geek/my_vimrc.git
git push -u origin master
  • 查看远程库的信息,用git remote ,用git remote -v显示更详细的信息
$ git remote
origin

$ git remote -v
origin  git@github.com:michaelliao/learngit.git (fetch)
origin  git@github.com:michaelliao/learngit.git (push)//有上传权才显示

git remote add pb git://github.com/paulboone/ticgit.git  添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用

git remote show [remote-name]
  • 本地上传分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交
    如果您当前分支的上游分支和您当前分支名不匹配,为推送到远程的上游分支,使用git push origin HEAD:LA_NS_Capsule
    为推送至远程同名分支,使用git push origin capsule
$ git push origin master
$ git push origin dev
git push origin –tags  如果要一次推送所有(本地新增的)标签上去,可以使用 --tags 选项

强制推送到远程仓库:git push -f 在提交错了,本地回退后提交时会提示落后于远程被拒绝,这个时候就可以用强制提交了
强制更新 git push -u origin +master

  • 本地创建和远程分支对应的分支,使用
    git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致

  • 建立本地分支和远程分支的关联,使用
    git branch --set-upstream branch-name origin/branch-name

$ git branch --set-upstream dev origin/dev
Branch dev set up to track remote branch dev from origin.
  • 从远程抓取分支,使用git pull,如果有冲突, 在本地合并,解决冲突,再推送
$ git pull
Auto-merging hello.py
CONFLICT (content): Merge conflict in hello.py
Automatic merge failed; fix conflicts and then commit the result.
  • 暂存了本地修改git stash解决冲突使用

git stash list 可以看到保存的信息,其中stash@{0}就是刚才保存的标记
git stash pop stash@{0} 还原暂存的内容
有冲突提示`冲突(内容):合并冲突于 文件
vim打开文件,查找如下表示:

<<<<<<< Updated upstream
上游更新内容
=======
本地暂存内容
>>>>>>> Stashed changes

其他命令
git stash save "save message" : 执行存储时,添加备注,方便查找,只有git stash 也要可以的,但查找时不方便识别。
git stash show:显示做了哪些改动,默认show第一个存储,如果要显示其他存贮,后面加stash@{KaTeX parse error: Expected 'EOF', got '}' at position 4: num}̲,比如第二个 git stas…num} -p ,比如第二个:git stash show stash@{1} -p
git stash apply:应用某个存储,但不会把存储从存储列表中删除,默认使用第一个存储,即stash@{0},如果要使用其他个,git stash apply stash@{KaTeX parse error: Expected 'EOF', got '}' at position 4: num}̲ , 比如第二个:git st…num} ,比如应用并删除第二个:git stash pop stash@{1}
git stash drop stash@{$num}:丢弃stash@{$num}存储,从列表中删除这个存储
git stash clear:删除所有缓存的stash

  • 下载的工程带有submodule

当使用git clone下来的工程中带有submodule时,初始的时候,submodule的内容并不会自动下载下来的,此时,只需执行如下> > 命令:git submodule update --init --recursive

  • 在当前分支创建标签git tag <name>就可以打一个新标签; 用-a指定标签名,-m指定说明文字; -s用私钥签名一个标签
$ git tag v1.0

$ git tag -a v0.1 -m "version 0.1 released" 3628164

$ git tag -s v0.2 -m "signed version 0.2 released" fec145a
  • 查看所有标签 git tag
$ git 
tagv1.0
  • 查看标签信息 git show <tagname>
$ git show v0.9commit 622493706ab447b6bb37e4e2a2f276a20fed2ab4
Author: Michael Liao <askxuefeng@gmail.com>
Date:  Thu Aug 22 11:22:08 2013 +0800

    add merge
...
  • 推送一个本地标签 git push origin <tagname>
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
 * [new tag]         v1.0 -> v1.0
  • 推送全部未推送过的本地标签 git push origin --tags
$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 554 bytes, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@github.com:michaelliao/learngit.git
 * [new tag]         v0.2 -> v0.2
 * [new tag]         v0.9 -> v0.9
  • 删除一个本地标签 git tag -d <tagname>
$ git tag -d v0.9
Deleted tag 'v0.9' (was 6224937)
  • 删除一个远程标签 git push origin :refs/tags/<tagname>
$ git push origin :refs/tags/v0.9
To git@github.com:michaelliao/learngit.git
 - [deleted]         v0.9

patch

  • 什么是patch?简单来讲,patch中存储的是你对代码的修改
  • 什么是生成patch?生成patch就是记录你对代码的修改并将其保存在patch文件中
  • 什么是打patch?打patch就是将patch文件中对代码的修改,应用到源代码,从而把对代码的修改应用到code中;
生成patch

命令:git format-patch

git format-patch -1 <r1> #生成单个commit的patch
git format-patch HEAD^              #生成最近的1次commit的patch
git format-patch HEAD^^              #生成最近的2次commit的patch
git format-patch HEAD^^^             #生成最近的3次commit的patch
git format-patch HEAD^^^^            #生成最近的4次commit的patch
git format-patch -M master 与分支比较生成patch,-M选项表示这个patch要和那个分支比对


git format-patch <r1>..<r2>                                              #生成两个commit间的修改的patch(包含两个commit. <r1>和<r2>都是具体的commit号)
git format-patch <r1>                                                       #生成某commit以来的修改patch(不包含该commit)
git format-patch --root <r1>               #生成从根到r1提交的所有patch
打patch

命令:git am

git apply --stat 0001-limit-log-function.patch         # 查看patch的情况
git apply --check 0001-limit-log-function.patch        # 检查patch是否能够打上,如果没有任何输出,则说明无冲突,可以打上
(注:git apply是另外一种打patch的命令,其与git am的区别是,git apply并不会将commit message等打上去,打完patch后需要重新git add和git commit,而git am会直接将patch的所有信息打上去,而且不用重新git add和git commit,author也是patch的author而不是打patch的人)
git am 0001-limit-log-function.patch                                # 将名字为0001-limit-log-function.patch的patch打上
git am --signoff 0001-limit-log-function.patch                  # 添加-s或者--signoff,还可以把自己的名字添加为signed off by信息,作用是注明打patch的人是谁,因为有时打patch的人并不是patch的作者
git am ~/patch-set/*.patch             # 将路径~/patch-set/*.patch 按照先后顺序打上
git am --abort                                                                   # 当git am失败时,用以将已经在am过程中打上的patch废弃掉(比如有三个patch,打到第三个patch时有冲突,那么这条命令会把打上的前两个patch丢弃掉,返回没有打patch的状态)
git am --resolved                                                             #当git am失败,解决完冲突后,这条命令会接着打patch
冲突解决
  • 如果不想打这一系列patch了,直接:git am --abort
  • 如果还想打:
    (1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch
    (2) 根据.rej文件,通过编辑该patch文件的方式解决冲突。
    (3) 废弃上一条am命令已经打了的patch:git am --abort
    (4) 重新打patch:git am ~/patch-set/*.patchpatch

####附录:

#####附录三:
实际提交gerrit,没有pull,提交上去反应冲突,需要解决

git reset --soft HEAD^2 切回提交之前,要提交的会在暂存区(操作之前代码备份一份,以防万一)
git log 查看是否切回
git pull 同步gerrit 仓库代码
git status 查看暂存区的提交是否正常
git commit -s 正常后再次提交,这个是最终要提交的commit id
git log -stat 查看提交文件是否正确
git add Platform.c 发现有个文件有多余的提交,修改后添加
git commit --amend 追加提交到刚才的commit id上
git push 将提交推到远程的gerrit仓库

#####附录四:
git pull 冲突,也可以用于所有冲突解决
git stash 暂存本地修改
stash list 查看暂存列表
git reset --hard 2b14d62 切回修改之前的分支
git pull 更新
git stash pop stash@{0} 还原暂存内容

提示冲突如下,进行解决

13:51:29-@code-server.gen  $ git stash pop stash@{0}
自动合并 Library/Ls7a1000Lib/Ls7aInitLib/Ls7a.c
自动合并 Include/Library/Ls7aInitLib.h
冲突(内容):合并冲突于 Include/Library/Ls7aInitLib.h
13:51:48-@code-server.gen  $ vim Include/Library/Ls7aInitLib.h
/<<<<<<< Updated upstream
#define LS7A_MISC_BASE                  (HT1_MEM_BASE_ADDR | MISC_BASE_ADDR)
#define LS7A_ACPI_BASE                  (LS7A_MISC_BASE | LS7A_ACPI_OFFSET)
#define LS7A_RTC_REG_BASE               (LS7A_MISC_BASE + LS7A_RTC_REG_OFFSE)
/=======
#define LS132ENA_BASE 0x900000001fe00000
#define LS132ENA_DYNAMIC_FREQ 0x0008
#define LS132ENA_RESET 0x420

#define LS7A_MISC_BASE   (HT1_MEM_BASE_ADDR | MISC_BASE_ADDR)
#define LS7A_ACPI_BASE   (LS7A_MISC_BASE | LS7A_ACPI_OFFSET)
/>>>>>>> Stashed changes
附录五:

GIt 追加上一次提交(保持Change-Id不变即可)
比如发现test.txt 文件忘记修改了

step1. vim test.txt修改
step2. git add test.txt
step3.git commit --amend 把文件和上次提交合并(追加提交)
说明
--amend 可以保持change_Id和上次一样,如果change-id被删掉的话,这条命令会生成新的chang_id,此时如果想合并到上次的修改中,必须复制上次的Change_Id作为本次的Change_id
step4.git push origin HEAD:refs/for/$branch
Gerrit中的一个Change就是一个Review任务,它对应一个commit。 每个commit,应该是为了一个目的的完整修改。如果某一次修改不完全,就需要修正该commit。
每一次修正之前的commit,重新提交时,都应该保持Change-Id不变,这样就不会产生新的Change,而是在原有的Change下产生一个新的Patch Set。
所有的Patch Set中,只有最新的一个是真正有用的,能够合并的。
用 --amend 选项,这种方式可以比较方便的保持原有的Change-Id,推荐使用。

附录六:
10:57:29-@code-server.gen  $ git push origin HEAD:refs/for/dev%r=mail1@.cn,r=mail2@.cn
Counting objects: 38, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (16/16), done.
Writing objects: 100% (16/16), 2.40 KiB | 0 bytes/s, done.
Total 16 (delta 10), reused 0 (delta 0)
remote: Resolving deltas: 100% (10/10)
remote: Processing changes: refs: 1, done    
To ssh://zhubo@rd.loongson.cn:29418/vUDK2018-loongson
 ! [remote rejected] HEAD -> refs/for/gen-dev%r=mail1@.cn,r=mail2@.cn (you are not allowed to upload merges)
error: 无法推送一些引用到 'ssh://@rd..cn:29418/master'

是由于已经有人提交了这个补丁,我进行了pull ,但补丁又被Abandoned了 ,所以打不上去。
方法一:笨办法
先将你的提交回退到上一版git reset --soft commitid
本地做保存git stash
回退到Abandned补丁之前的版本 git reset --hard commitid
恢复本地保存:git stash pop stash @{0}
进行本地爱add commit -s
推到远程仓库 git push origin HEAD:refs/for/dev
方法二:
现在去打开这个补丁提交的greeit restore回来就可以了 ,网上的方式,还没实现

附录七:

不修改代码只修改log
1、如果是最近提交的log
在最近提交进行追加提交git commmit --amend
查看是否修改:git log
强制推送到远程仓库:git push -f
2、修改历史log
查看log,确定修改哪条log,复制比它还老的commit id git log
列出commitid之前的log ,如下 git rebase -i commitid

pick e76cb12 更新了grep搜索的包含文件类型
pick d016f28 csc 显示目录深度改成了5
pick 33dead5 填加了tab的切换标志 commit --amend

# Rebase 57e3145..33dead5 onto 57e3145
……

将第一个pick 修改为edit, 然后:wq退出,会显示如下信息,如果要改日志,执行git commit --amend,如果修改完成后,执行git rebase --continue

Stopped at d016f28... csc 显示目录深度改成了5
You can amend the commit now, with
	git commit --amend
Once you are satisfied with your changes, run
	git rebase --continue

修改日志git commit --amend
修改完成 git rebase --continue
打印信息

18:02:51-@code-server.gen vim-init $ git commit --amend
[分离头指针 d4d659e] csc 显示目录深度改成了5 git rebase -i commitid Signed-off-by: user <user@.cn>
 1 file changed, 1 insertion(+), 1 deletion(-)
18:04:00-@code-server.gen vim-init $ git rebase --continue
Successfully rebased and updated refs/heads/master.

查看是否修改:git log
强制推送到远程仓库:git push -f

附录八:
回退提交后的某个文件,不是最近一次提交,是之前的某个commitid
1、获取想要回退到的版本的commit id(假设为2fe1167)
2、git 回退版本git reset 2fe1167 test.txt
3、回退之后查看当前状态 会发现没有如想象中的回退到那个版本
4、回退后会到暂存区,确认没有问题后在进行提交就好了

附录九:
多次commit log 合并成一个;
使用git merge 通过分支之间的合并用参数--squash将原有分支的上的多次commit 合并过来做一次commit

git checkout another
git merge --squash another
git commit -m "message here"

--squash含义和原理如下:
–squash选项的含义是:本地文件内容与不使用该选项的合并结果相同,但是不提交、不移动HEAD,因此需要一条额外的commit命令。其效果相当于将another分支上的多个commit合并成一个,放在当前分支上,原来的commit历史则没有拿过来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值