Git学习笔记

本文详细介绍了Git的安装配置、基本操作,包括添加、提交、回退、分支管理和多人协作。讲解了如何创建、切换、合并分支,处理冲突,以及使用标签进行版本管理。此外,还涵盖了Git的忽略文件、颜色配置、别名设置和一些高级用法,如cherry-pick和rebase。
摘要由CSDN通过智能技术生成

Git学习笔记


1. Git安装及推荐配置

下载GIt,选择相应版本。

  1. 安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。

$ git config --global user.name “李老师
$ git config --global user.email li@csdn.net

注意:
如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。

  1. 检查你的配置
git config --list   
  1. 让 Git 显示颜色,会让命令输出看起来更醒目:

$ git config --global color.ui true

  1. 忽略文件
    有些时候,你必须把某些文件放到 Git 工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件等等,每次git status都会显示Untracked files …,这种情况下,就可以用忽略特殊文件 .gitignore 来很方便的解决这个问题

在 Git 工作区的根目录下创建一个特殊的 .gitignore文件,然后把要忽略的文件名填进去,Git 在每次进行提交的时候就会自动忽略这些文件。

例子:

  • 你需要忽略 Windows 自动生成的垃圾文件:
  • 忽略Python编译产生的.pyc、.pyo、dist等文件或目录:
  • 加上你自己定义的文件,最终得到一个完整的.gitignore文件
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini

# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build

# My configurations:
db.ini
deploy_key_rsa
  • 最后一步就是把.gitignore也提交到 Git,就完成了!当然检验.gitignore的标准是git status命令是不是说working directory clean

  • 有些时候,你想添加一个文件到 Git,但发现添加不了,

    • 原因是这个文件被.gitignore忽略了, 强制添加被忽略文件
      $ git add -f App.class

    • 可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:
      $ git check-ignore -v App.class

  • 添加两条例外规则:

# 排除所有.开头的隐藏文件:
.*
# 排除所有.class文件:
*.class

# 不排除.gitignore和App.class:
!.gitignore
!App.class
  1. 配置别名
    只需要敲一行命令,告诉 Git,以后st就表示status:
$ git config --global alias.st status
$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch

   配置完成以上别名后,以后提交就可以简写成:$ git ci -m "sth."
  1. 配置 git reset HEAD file
    git reset HEAD file命令,他可以把暂存区的修改撤销掉(unstage),重新放回工作区。既然是一个unstage操作,就可以配置一个unstage别名:
    $ git config --global alias.unstage 'reset HEAD'

  2. 配置 git log -1

    $ git config --global alias.last 'log -1'

    用git last就能显示最近一次的提交

  3. 配置 git lg

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

以上这些就是 git 常用的一些配置了。


  1. 配置文件
    这些自定义的配置文件通常都存放在仓库的.git/config文件中:

    git config -e --global
    查看全局配置

2.git的使用

2.1 在已存在目录中初始化仓库 —— git init

在已存在目录中创建一个版本库的过程非常简单
首先,选择一个合适的地方,创建一个空目录
第二步,通过git init命令把这个目录变成 Git 可以管理的仓库

  1. 创建目录
$ mkdir learning-git
$ cd learning-git
$ pwd
/Users/xxm/learning-git
  1. 初始化仓库
$ git init
Initialized empty Git repository in /Users/xxm/learning-git/.git/

瞬间 Git 就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),同时在当前目录下多了一个.git的目录

2.2 克隆现有的仓库 —— git clone

当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来 git clone <url>

例:$ git clone https://codechina.csdn.net/codechina/help-docs
这会在当前目录下创建一个名为 help-docs 的目录,并在这个目录下初始化一个 .git 文件夹, 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。 如果你进入到这个新建的 help-docs 文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。

自定义本地仓库名称

当然如果你想在克隆远程仓库的时候,自定义本地仓库的名字也是可以的,你可以通过额外的参数指定新的目录名

$ git clone https://codechina.csdn.net/codechina/help-docs mydocs

这会执行与上一条命令相同的操作,但目标目录名变为了 mydocs。

Git 支持多种数据传输协议。 上面的例子使用的是 https:// 协议,不过你也可以使用 git:// 协议或者使用 SSH传输协议,比如 user@server:path/to/repo.git 。

2.3 提交文件操作

第一步,用命令git add告诉 Git,把文件添加到仓库:

第二步,用命令git commit告诉 Git,把文件提交到仓库:

例如:
Git 仓库中编辑一个readme.txt文件,内容如下:

 Git is a version control system.
Git is free software.
$ git add readme.txt
//执行上面的命令,没有任何显示,说明添加成功。
$ git commit -m "wrote a readme file"
  1. -m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
  2. git commit命令执行成功后会告诉你:
    1 file changed:1个文件被改动(我们新添加的readme.txt文件)
    2 insertions:插入了两行内容(readme.txt有两行内容)

为什么 Git 添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:

$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

已经成功地添加并提交了一个readme.txt文件,接下来让我们继续修改readme.txt文件,改成如下内容:

Git is a distributed version control system.
Git is free software.

运行git status命令看看结果:

$ git status
On branch master
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

no changes added to commit (use "git add" and/or "git commit -a")

git status命令可以让我们时刻掌握仓库当前的状态,上面的命令输出告诉我们,readme.txt被修改过了,但还没有准备提交的修改。

git diff这个命令查看相较于上一次暂存都修改了些什么内容了:

$ git diff readme.txt 
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
 Git is free software.
 (END)

git diff顾名思义就是查看 difference,显示的格式正是 Unix 通用的 diff 格式,可以从上面的输出看到,我们在第一行添加了一个distributed单词。

  • git log命令显示从最近到最远的提交日志
  • 如果嫌输出信息太多,看得眼花缭乱的,可以试试加上–pretty=oneline参数: git log --pretty=oneline
$ git lg
* e55063a - (HEAD -> master) add distributed (4 minutes ago) <Miykael_xxm>
* 50ed06b - wrote a readme file (6 minutes ago) <Miykael_xxm>
(END)

2.4 回退提交文件

  • 假设我们需要将 readme.txt 回退到上一个版本,也就是 wrote a readme file 的这个版本,使用git reset

在 Git 中,用HEAD表示当前版本,也就是最新的提交e55063a,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。

$ git reset --hard HEAD^
HEAD is now at 50ed06b wrote a readme file

Git 的版本回退速度非常快,因为 Git 在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git 仅仅是把HEAD从指向add distributed

  • 回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?

git reflog用来记录你的每一次命令,当你用git reset --hard HEAD^回退到wrote a readme file版本时,再想恢复到add distributed,就可以通过git reflog命令找到add distributed的commit id

$ git reflog
50ed06b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~
e55063a HEAD@{1}: reset: moving to HEAD
e55063a HEAD@{2}: commit: add distributed
50ed06b (HEAD -> master) HEAD@{3}: commit (initial): wrote a readme file
ESC

从上面的输出可以看到,add distributed的commit id是e55063a,现在,我们就可以通过 git reset --hard e55063a切换到最新的版本上了。


总结:

  • git init
  • git clone
  • git add
  • git commit
  • git status
  • git diff
  • git log
  • git reset
  • git reflog

3.版本控制

1.有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令来重新提交:

  git commit --amend

这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),
那么快照会保持不变,而你所修改的只是提交信息。

例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

最终你只会有一个提交——第二次提交将代替第一次提交的结果。

当你在修补最后的提交时,并不是通过用改进后的提交 原位替换 掉旧有提交的方式来修复的,
理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。

2.如何操作暂存区和工作目录中已修改的文件。

这些命令在修改文件状态的同时,也会提示如何撤消操作

例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入 git add * 暂存了它们两个。如何只取消暂存两个中的一个呢? git status 命令提示了你:

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    LICENSE -> LICENSE.md
    modified:   readme.txt

在 “Changes to be committed” 文字正下方,提示使用 git reset HEAD … 来取消暂存。 所以,我们可以这样来取消暂存 readme.txt 文件:

$ git reset HEAD readme.txt
Unstaged changes after reset:
M	readme.txt

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    LICENSE -> LICENSE.md

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

如果你不想保留对文件的修改怎么办?如何方便地撤消修改——将它还原成上次提交时的样子

git checkout – file

$ git checkout -- readme.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    LICENSE -> LICENSE.md

git checkout – 是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。

删除文件之后的操作
添加一个新文件test.txt到 Git 并且提交

$ git add test.txt

$ git commit -m "add test.txt"
[master c67077f] add test.txt
 1 file changed, 1 insertion(+)
 create mode 100644 test.txt

若在文件管理器中把文件删了,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:

$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	deleted:    test.txt

no changes added to commit (use "git add" and/or "git commit -a")

一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit:

$ git rm test.txt
rm 'test.txt'

$ git commit -m "remove test.txt"
[master 5c7e5ea] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

$ git checkout -- test.txt

回顾:

  • 场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout – file

  • 场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作

  • 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,可以用命令git reset --hard commit_id,不过前提是没有推送到远程库

4.分支管理

1. dev分支

$ git checkout -b dev
Switched to a new branch 'dev'

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

$ git branch dev
$ git checkout dev
Switched to branch 'dev'

用git branch命令查看当前分支

$ git branch
* dev
  master

git branch命令会列出所有分支,当前分支前面会标一个*号。
在dev分支上的操作,master分支此刻的提交点并没有变

用 git merge 把dev分支的工作成果合并到master分支上:

$ git merge dev
Updating 599dbdb..4aac6c7
Fast-forward
 readme.txt | 1 +
 1 file changed, 1 insertion(+)

合并完成后,就可以放心地删除dev分支了:

 $ git branch -d dev
Deleted branch dev (was 4aac6c7).

删除后,查看branch,就只剩下master分支了。

*切换分支使用git checkout ,而 Git 中撤销修改则是git checkout – ,同一个命令,有两种作用,确实有点令人迷惑。 *

最新版本的 Git 提供了新的git switch命令来切换分支:
创建并切换到新的dev分支,可以使用:

$ git switch -c dev

直接切换到已有的master分支,可以使用:

$ git switch master

通常,合并分支时,如果可能,Git 会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git 就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

$ 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 log看看分支历史:

$ git log --graph --pretty=oneline --abbrev-commit
*   fc76cf7 (HEAD -> master) merge with no-ff
|\  
| * f52c633 (dev) add merge
|/  
*   cf810e4 conflict fixed
...

不使用Fast forward模式,merge后就像这样:
在这里插入图片描述
几个基本原则进行分支管理:

  • 首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
  • 其次,干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,并在master分支发布1.0版本;
    dev分支

2. bug分支

接到一个修复一个代号101的 bug 的任务时,很自然地,你想创建一个分支 issue-101 来修复它,但是,当前正在dev上进行的工作还没有提交:
当前工作只进行到一半,还没法提交,但是,必须在两个小时内修复该 bug怎么办?
幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge

用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复 bug。
首先确定要在哪个分支上修复 bug,假定需要在master分支上修复,就从master创建临时分支:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)

$ git checkout -b issue-101
Switched to a new branch 'issue-101'

修复bug,然后提交:

$ git add readme.txt 
$ git commit -m "fix bug 101"
[issue-101 8842ff5] fix bug 101
 1 file changed, 1 insertion(+), 1 deletion(-)

修复完成后,切换到master分支,并完成合并,最后删除issue-101分支:

$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)

$ git merge --no-ff -m "merged bug fix 101" issue-101
Merge made by the 'recursive' strategy.
 readme.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

接着回到dev分支干活了!

$ git switch dev
Switched to branch 'dev'

$ git status
On branch dev
nothing to commit, working tree clean

用git stash list命令看看刚才的工作现场:

$ git stash list
stash@{0}: WIP on dev: f52c633 add merge

工作现场还在,Git 把stash内容存在某个地方了,但是需要恢复一下,有两个办法:

  • 一是用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} (5d677e2ee266f39ea296182fb2354265b91b3b2a)

再用git stash list查看,就看不到任何stash内容了:

你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:git stash apply stash@{0}

在master分支上修复了bug后,我们要想一想,dev分支是早期从master分支分出来的,所以,这个bug其实在当前dev分支上也存在。
怎么在dev分支上修复同样的bug?
只需要把8842ff5 fix bug 101这个提交所做的修改“复制”到dev分支。

Git 专门提供了一个cherry-pick命令,让我们能复制一个特定的提交到当前分支:

$ git branch
* dev
  master
$ git cherry-pick 8842ff5
[dev 0944c8c] fix bug 101
 1 file changed, 1 insertion(+), 1 deletion(-)

3. feature分支

每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。
feature分支和bug分支是类似的,合并,然后删除。
但是!就在此时,新功能必须取消!须就地销毁:

$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.

销毁失败。Git 友情提醒,feature-vulcan分支还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D参数

$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was d12cf23).

删除成功!

解决合并请求中的冲突

Git 无法执行“快速合并”,只能试图把各自的修改合并起来

Cherry Pick

git cherry-pick命令的作用,就是将指定的提交commit应用于其他分支。

$ git cherry-pick <commitHash>

上面命令就会将指定的提交commitHash,应用于当前分支。这会在当前分支产生一个新的提交,当然它们的哈希值会不一样。

Cherry pick 支持一次转移多个提交。

$ git cherry-pick <HashA> <HashB>

上面的命令将 A 和 B 两个提交应用到当前分支。这会在当前分支生成两个对应的新提交。

  1. -e,–edit
    打开外部编辑器,编辑提交信息。
  2. -n,–no-commit
    只更新工作区和暂存区,不产生新的提交。
  3. -x
    在提交信息的末尾追加一行cherry picked from commit …,方便以后查到这个提交是如何产生的。
  4. -s,–signoff
    在提交信息的末尾追加一行操作者的签名,表示是谁进行了这个操作。
  5. -m parent-number,–mainline parent-number
    如果原始提交是一个合并节点,来自于两个分支的合并,那么 Cherry pick 默认将失败,因为它不知道应该采用哪个分支的代码变动。
    -m配置项告诉 Git,应该采用哪个分支的变动。它的参数parent-number是一个从1开始的整数,代表原始提交的父分支编号。
$ git cherry-pick -m 1 <commitHash>

上面命令表示,Cherry pick 采用提交commitHash来自编号1的父分支的变动。
一般来说,1号父分支是接受变动的分支,2号父分支是作为变动来源的分支。


如果操作过程中发生代码冲突,Cherry pick 会停下来,让用户决定如何继续操作。
(1)--continue
用户解决代码冲突后,第一步将修改的文件重新加入暂存区(git add .),第二步使用下面的命令,让 Cherry pick 过程继续执行。
$ git cherry-pick --continue
(2)--abort
发生代码冲突后,放弃合并,回到操作前的样子。
(3)--quit
发生代码冲突后,退出 Cherry pick,但是不回到操作前的样子。


5.多人协作

 git rebase

6.git标签

发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。
Git 的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。

  1. 切换到需要打标签的分支上
 $ git branch
* dev
  master
$ git checkout master
Switched to branch 'master'
  1. git tag 就可以打一个新标签:
$ git tag v1.0
  1. 用命令git tag查看所有标签:
$ git tag
v1.0
  • 也可以$ git tag v0.9 fb8b190

  • 还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:

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

用命令git show 可以看到说明文字

注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。

删除 tag

$ git tag -d v0.1
Deleted tag 'v0.1' (was 94e0f81)

因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除

推送 tag

$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To codechina.csdn.net:xiongjiamu/learning-git.git
 * [new tag]         v1.0 -> v1.0

一次性推送本地 tag

$ git push origin --tags
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 171 bytes | 171.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To codechina.csdn.net:xiongjiamu/learning-git.git
 * [new tag]         remove -> remove
 * [new tag]         v0.1 -> v0.1
 * [new tag]         v0.9 -> v0.9

删除已推送的 tag

  1. 先从本地删除
$ git tag -d remove
Deleted tag 'remove' (was c47983c)
  1. 然后,从远程删除
 $ git push origin :refs/tags/remove
To codechina.csdn.net:xiongjiamu/learning-git.git
 - [deleted]         remove

总结:

  1. 命令git push origin <tagname>可以推送一个本地标签;
  2. 命令git push origin --tags可以推送全部未推送过的本地标签;
  3. 命令git tag -d <tagname>可以删除一个本地标签;
  4. 命令git push origin :refs/tags/<tagname>可以删除一个远程标签
  5. 命令git tag -a <tagname> -m 'messages'可以创建一个带附注的标签
  6. 命令git tag -s <tagname> -m 'messages'可以创建一个带 gpg 签名的标签
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值