Git学习笔记
本文更新于2024-08-26,使用git 2.19.0,操作系统为Windows 10。
官方中文文档:https://git-scm.com/book/zh/v2。
说明:下文中,大写为自定义变量,根据实际情况填写(个别大写的参数除外)。使用[]
引起表示内容可选,|
表示使用左侧或右侧内容,...
表示重复之前内容。
- 安装
- 运行机制
- 配置文件
- .gitignore
- 选择指定的提交
- 上层命令
- git add
- git bisect
- git blame
- git branch
- git bundle
- git checkout
- git cherry-pick
- git clean
- git clone
- git config
- git commit
- git credential
- git diff
- git fetch
- git gc
- git grep
- git gui
- git help
- git init
- git log
- git ls-remote
- git merge
- git merge-file
- git mergetool
- git mv
- git pull
- git push
- git rebase
- git reflog
- git remote
- git replace
- git rerere
- git reset
- git rev-parse
- git revert
- git rm
- git show
- git stash
- git status
- git submodule
- git tag
安装
在Debian 10安装:
sudo apt-get install git
运行机制
Workspace Index/Stage Repository Remote
| | | |
| add | commit | push |
|------------->|------------>|------------>|
| checkout | fetch |
|<---------------------------|<------------|
| pull |
|<-----------------------------------------|
- 工作区(Workspace):计算机中看到的目录,持有实际文件。工作区下每个文件都处于以下两种状态之一:
- 已跟踪:被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改、已修改、已暂存、已提交。
- 未跟踪:除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。
- 暂存区(Index/Stage):临时保存改动。
- 版本库(Repository):工作区目录下的.git目录。
- 远程仓库(Remote):托管在远程计算机上的版本库,可供多人分布式开发。
下文中的.目录均为工作区,命令均在工作区下执行。
配置文件
Linux配置文件读取顺序:
- /etc/gitconfig
- ~/.gitconfig或~/.config/git/config
- .git/config
Windows配置文件读取顺序:
- C:/Users/$USER/.gitconfig
- .git/config
.gitignore
配置忽略跟踪的文件列表。若文件已被跟踪,则规则对其无效。
- 以#开头的行是注释。
- 使用glob模式匹配的文件或目录,均忽略跟踪。以/开头表示工作区根目录,以/结尾表示目录。
- *匹配零个或多个任意字符。
- ?匹配任意一个字符。
- [abc]匹配列表中任意一个字符。
- [a-z]匹配范围内任意一个字符。
- **匹配任意中间目录。
- 在模式前加!,可强制跟踪该模式,即使该模式被其他模式指定为忽略跟踪。但如已忽略跟踪该模式的父目录,则使用!也不能强制跟踪。
选择指定的提交
命令行中可以使用如下方式,选择指定的提交(记为COMMIT):
- 使用40个字符的完整哈希值(记为HASH)。
- 使用哈希值的前缀,最少4个字符。
- 使用分支名(记为BRANCH),选择分支最顶端的提交。
- 使用BRANCH@{N},BRANCH为分支名,N为整数,选择分支前N次的提交,N为0表示分支最顶端的提交。
- 使用^选择父提交,可连续使用多次选择祖先提交。
- 使用^N选择指定的父提交,只用于合并的提交,此时第一个父提交为合并时所在的分支,第二个父提交为被合入的分支。
- 使用~选择父提交,可连续使用多次选择祖先提交,也可使用~N简写表示连续N个~。
上层命令
查看版本:
git --version
常用流程:
- git clone 克隆远程仓库。
- git config 配置。
- git status 查看文件状态。
- git diff 查看差异。
- git add 暂存。
- git reset 重置暂存区或工作区。
- git commit 提交。
- git log 查看提交记录。
- git branch 创建分支。
- git checkout 切换分支。
- git merge 合并分支。
- git mergetool 解决冲突。
- git fetch 从远程仓库拉取。
- git push 推送至远程仓库。
- git tag 创建标签。
git add
将文件放入暂存区。如匹配目录,则暂存目录下的所有文件。可用于跟踪新文件,暂存已修改文件,合并时将冲突标记为已解决:
git add PATTERN[ ...]
进入交互式暂存:
git add -i|--interactive
交互式暂存可输入以下子命令:
- 1或s:status,查看暂存状态。
- 2或u:update,暂存文件。
- 3或r:revert,撤销暂存文件。
- 4或a:add untracked,添加未跟踪的文件。
- 5或p:patch:暂存文件的特定部分。
- 6或d:diff,查看已暂存文件的差异。
- 7或q:quit,退出交互式暂存。
- 8或h:help,查看帮助。
输入子命令后,会列出带标号的文件列表。可使用“?”查看帮助,可以如下选择文件:
- 标号:选中单个文件,如:1。
- 标号1-标号2:选中文件范围,如:3-5。
- ,分隔的标号或标号区间:选中多个文件范围,如:2-3,6-9。
- 文件名前缀:选中带有此前缀的文件。
- -开头:取消选中。
- *:选中所有文件。
- 回车:结束并确认选择。
输入5或p,选择文件后,进入交互式部分暂存,可输入以下子命令:
- y:暂存此块文件内容。
- n:不暂存此块文件内容。
- a:暂存此块及本文件中所有后续块的文件内容。
- d:不暂存此块及本文件中所有后续块的文件内容。
- g:选择跳至一个块。
- /:选择匹配给定正则表达式的块。
- j:不决定本块是否暂存,离开并跳至下一个未决定的块。
- J:不决定本块是否暂存,离开并跳至下一个块。
- k:不决定本块是否暂存,离开并跳至上一个未决定的块。
- K:不决定本块是否暂存,离开并跳至上一个块。
- s:将当前块分割成更小的块。
- e:手工编辑当前块。
- ?:查看帮助。
进入交互式部分暂存:
git add -p|--patch
git bisect
二分查找出有问题的提交。
git blame
查看文件标注,可查看每一行分别来自那次提交:
git blame [-C] [-L STARTLINE,ENDLINE] NAME[ ...]
每行的结果包括以下内容:
- 最后一次修改的提交哈希,以^开头表示从未修改。
- 原始文件名,当使用-C时出现,表示行内容从此文件复制过来。
- 提交者。
- 提交时间。
- 文件行内容。
git branch
创建分支。不会切换到新分支:
git branch BRANCH [COMMIT]
删除分支:
git branch -d BRANCH
强制删除分支。如果分支包含未合并的提交,则会将其丢弃:
git branch -D BRANCH
删除远程分支:
git branch -dr REMOTE/BRANCH
设置本地分支跟踪的远程分支。当设置好跟踪分支后,可以通过@{upstream}
或@{u}
快捷方式来引用它:
git branch -u|--set-upstream [BRANCH] REMOTE/BRANCH
查看所有本地分支。使用-v参数可查看每一个分支的最后一次提交。使用-vv参数可查看所有跟踪分支:
git branch
git branch -v
git branch -vv
查看所有远程分支:
git branch -r
查看所有本地分支和远程分支:
git branch -a
查看已合并到当前分支的分支:
git branch --merged
查看未合并到当前分支的分支:
git branch --no-merged
git bundle
打包提交。
git checkout
将HEAD、暂存区和工作区切换至指定的提交:
git checkout COMMIT
切换分支:
git checkout BRANCH
切换到上一个分支:
git checkout -
创建并切换分支:
git checkout -b BRANCH [COMMIT]
交互式检出文件:
git checkout --patch COMMIT
解决冲突后检出文件:
git checkout --conflict=merge|diff3 FILENAME
解决冲突时检出当前分支原来的文件:
git checkout --ours FILENAME
解决冲突时检出待合入分支的文件:
git checkout --theirs FILENAME
检出暂存区的文件至工作区:
git checkout [--] FILE[ ...]
检出某次提交的文件至工作区:
git checkout COMMIT FILE[ ...]
git cherry-pick
将提交在当前分支重放,不影响原有提交:
git cherry-pick COMMIT
git clean
清理工作区,移除未被追踪的文件:
git clean
强制清理:
git clean -f
同时移除未跟踪的目录:
git clean -d
同时移除忽略跟踪的文件:
git clean -x
查看清理将移除的文件,但不实际移除:
git clean -n|--dry-run
交互式清理:
git clean -i
git clone
克隆仓库。如没有指定目标目录,则会在当前目录下以源路径最后一个目录名为目标目录。目标目录必须为空目录:
git clone SRC [DST]
git config
查看配置:
git config --list
git config KEY
编辑配置:
git config -e [--global]
设置配置:
git config [--global] alias.ALIAS SOURCE
git config [--global] core.autocrlf true|input|false
git config --bool core.bare true|false
git config [--global] core.editor EDITOR
git config [--global] core.ignorecase true|false
git config [--global] core.quotepath true|false
git config [--global] credential.helper cache|store|osxkeychain
git config --system --unset credential.helper
git config [--global] gui.encoding ENCODING
git config [--global] http.sslVerify true|false
git config [--global] merge.conflictstyle merge|diff3
git config [--global] merge.tool MERGETOOL
git config [--global] mergetool.MERGETOOL.path PATH
git config [--global] pull.rebase true|false
git config [--global] user.email EMAIL
git config [--global] user.name NAME
- alias:如果SOURCE是外部命令,则需在前面加!。
- core.autocrlf:为true则checkout时转换为CRLF,commit时转换为LF;为input则checkout时不做转换,commit时转换为LF;为false则checkout和commit时都不做转换。强烈建议将此值设置为--global的false。
- core.bare:是否设为裸仓库。裸仓库可作为远程仓库往其push。
- core.editor:默认编辑器。
- core.ignorecase:是否忽略文件路径中大小写的不同。
- core.quotepath:是否将文件路径中0x80以上的字符转义为八进制。
- credential.helper:凭证存储方式。cache为保存在内存中,可附加参数--timeout SECONDS;store为明文保存在磁盘中,可附加参数--file FILENAME;osxkeychain在Mac下使用,密文保存在磁盘中。如需清除之前保持的凭证(例如:提示“You are not allowed to push code to this project.”),则使用--system --unset。
- gui.encoding:GUI中的字符编码,如:utf-8。
- http.sslVerify:当使用HTTPS从远程仓库推送或拉取时是否使用SSL证书验证。当提示“OpenSSL SSL_read: Connection was reset, errno 10054”时可能需设置为false。
- merge.conflictstyle:合并冲突时冲突的样式。merge有ours、theirs的数据,diff3有ours、theirs、base的数据。
- merge.tool:合并冲突的工具,如:kdiff3。需同时指定mergetool.MERGETOOL.path。
- mergetool.MERGETOOL.path:合并冲突的工具的可执行文件路径。MERGETOOL需与merge.tool指定的值相同。
- user.email:作者邮箱。
- user.name:作者名字。
常用配置:
git config core.autocrlf false
git config core.ignorecase false
git config core.quotepath false
git config gui.encoding utf-8
git config user.name NAME
git config user.email NAME@EMAIL.COM
删除配置:
git config --unset KEY
git commit
将暂存区提交:
git commit [NAME[ ...]]
将已跟踪过的文件暂存并提交:
git commit -a
提交时注明备注信息:
git commit -m MSG
撤销上一次提交,重新提交:
git commit --amend
允许没有改动的提交:
git commit --allow-empty
提交时跳过pre-commit和commit-msg的钩子:
git commit --no-verify
提交时显示差异信息:
git commit -v
git credential
凭证辅助工具。
git diff
比较工作区相对于暂存区的差异:
git diff
比较暂存区相对于已提交的差异:
git diff --staged|--cached
比较COMMIT2相对于COMMIT1的差异:
git diff COMMIT1 COMMIT2
比较时忽略空白符的差异:
git diff -b
比较时只列出有差异的文件名:
git diff --name-only
比较合并的结果与当前分支原来的差异:
git diff --ours
比较合并的结果与待合入分支的差异:
git diff --theirs
三路比较合并差异:
git diff --base
git fetch
从远程仓库拉取。不会自动合并分支:
git fetch [REMOTE REMOTEBRANCH]
拉取所有远程仓库:
git fetch --all
从远程仓库拉取所有标签:
git fetch --tags
删除不存在于远程仓库的本地跟踪引用:
git fetch --prune
git gc
清理垃圾文件。
git gc
git grep
搜索文件内容,可搜索工作区和所有提交:
git grep [OPTIONS] REGEXP
OPTIONS可使用如下选项:
- -c或--count:只显示匹配的计数概要。
- -n或--line-number:显示匹配的行号。
- -p或--show-function:显示匹配的行所在的函数。
- --and:同一行同时匹配多个值。
- --break:在不同文件的匹配之间显示空行。
- --heading:在同一个文件的匹配之前显示文件名。
git gui
打开图形用户界面:
git gui
git help
查看帮助:
git help VERB
git VERB --help
man git-VERB
git init
在当前目录初始化仓库。目录中可以存在文件。远程仓库最好使用--bare参数初始化,且之后仓库不能作为工作区:
git init [--bare]
在当前目录的子目录初始化仓库。
git init DIR
git log
查看分支的提交历史:
git log [OPTIONS] [BRANCH ...]
查看指定文件的提交历史:
git log [OPTIONS] FILENAME[ ...]
双点(..为命令行输入的字符)查看提交区间,查看在BRANCH2中而不在BRANCH1中的提交历史:
git log [OPTIONS] BRANCH1..BRANCH2
三点(...为命令行输入的字符)查看提交区间,查看被两个分支之一包含,但不被同时包含的提交:
git log [OPTIONS] [--left-right] BRANCH1...BRANCH2
指定--left-right后,输出使用“<”和“>”表示提交属于左侧的分支还是右侧的分支。
多点查看提交区间,使用^或--not指定提交不在其中的分支:
git log [OPTIONS] BRANCH1 [ ...] [^BRANCH2 [ ...]] [--not BRANCH3 [ ...]]
OPTIONS可使用如下选项:
- 基本选项:
- -- PATH:放在最后位置上,指定文件路径。
- -L :FUNCNAME:FILENAME或-L '/REGEXP/':FILENAME:行日志搜索,查看指定函数的提交历史。
- --decorate:查看各个分支当前所指的对象。
- 提交范围选项:
- -(N):最近n次提交。如:-20。
- -g:显示引用日志,即类似git reflog。
- --after TIME:显示指定时间之后的提交,同--since。
- --all:显示所有分支的提交信息。
- --all-match:显示同时满足这所有选项搜索条件的提交,不带此选项则显示满足任意一个搜索条件的提交。
- --author AUTHOR:显示指定作者相关的提交。
- --before TIME:显示指定时间之前的提交,同--until。
- --committer COMMITTER:显示指定提交者相关的提交。
- --grep WORD:显示提交说明(即git commit -m指定的内容)中含指定关键字的提交。
- --since TIME:显示指定时间之后的提交,同--after。
- --until TIME:显示指定时间之前的提交,同--before。
- 提交排序选项:
- --date-order:按提交时间排序。
- 格式化选项:
- --abbrev-commit:仅显示SHA-1的前几个字符,而非所有的40个字符。
- --graph:使用ASCII图表展示分支,需与--pretty=oneline|format结合使用。
- --oneline:每次提交信息单行显示,类似--pretty=oneline。
- --pretty=oneline|short|full|fuller|format:"FORMAT":使用指定格式显示。
- --relative-date:使用较短的相对时间显示(比如,“2 weeks ago”)。
- 差异比较选项:
- -G REGEXP:显示提交文件内容中匹配正则表达式的提交。
- -p [FILENAME]:显示每次提交的内容差异,可只查看指定文件的差异。
- -S WORD:显示提交文件内容中含指定关键字的提交。
- --name-only:仅在提交信息后显示已修改的文件清单。
- --name-status:显示新增、修改、删除的文件清单。
- --shortstat:只显示--stat中最后的行数修改添加移除统计。
- --stat:显示每次提交的简略的统计信息。
常用功能:
- 查看分支历史图表:git log --oneline --graph --all -(N)
- 搜索文件内容:git log -S WORD --all
git ls-remote
更新远程仓库的所有引用至本地并显示:
git ls-remote [REMOTE]
更新远程仓库的标签至本地并显示:
git ls-remote --tags [REMOTE]
git merge
将提交合并到当前分支:
git merge COMMIT
将提交合并到当前分支,总是创建一个提交而不使用快进(fast-forward):
git merge --no-ff COMMIT
将没有共同祖先提交的不关联分支合并到当前分支:
git merge --allow-unrelated-histories COMMIT
合并时忽略空白:
git merge -Xignore-all-space|-Xignore-space-change COMMIT
- -Xignore-all-space: 完全忽略空白符的修改。
- -Xignore-space-change:将一个空白符与多个连续的空白字符视作等价的。
合并时冲突使用当前分支的内容:
git merge -Xours COMMIT
合并时冲突使用待合入分支的内容:
git merge -Xtheirs COMMIT
中断合并:
git merge --abort
如有合并冲突,需使用git mergetool
解决,然后执行git add
和git commit
。
git merge-file
合并文件,如使用-p则将结果打印而不是写入CURRENTFILENAME:
git merge-file [-p] CURRENTFILENAME BASEFILENAME OTHERFILENAME
使用当前分支的内容合并文件:
git merge-file --ours FILENAME
使用待合入分支的内容合并文件:
git merge-file --theirs FILENAME
git mergetool
可视化合并冲突解决:
git mergetool [FILENAME]
使用kdiff3合并:A(Base)为共同祖先;B(Local)为当前分支;C(Remote)为待合入的分支;Ouput为合并结果。合并成功后,会保存后缀为.orig的冲突文件,其中描述的冲突内容如下:
- "<<<<<<<"表示本地分支,其后跟随本地分支名。
- 本地分支内容。
- "======="分隔本地分支和待合入的分支。
- 待合入分支内容。
- ">>>>>>>"表示待合入分支,其后跟随待合入分支名。
合并冲突解决后,需使用git commit
提交。
kdiff3可通过设置修改字符编码:“Settings -> Configure KDiff3... -> Regional Settings”,选择“File Encoding for”开头的对应下拉框为“Unicode, 8 bit (UTF-8)”。
git mv
移动文件(即使在大小写不敏感的文件系统中也可修改大小写):
git mv FROM TO
git pull
从远程仓库拉取。会自动合并到跟踪分支。通常单独显式地使用fetch与merge命令会更好一些:
git pull [--rebase] [REMOTE [BRANCH]]
git pull --allow-unrelated-histories [REMOTE [BRANCH]]
当本地仓库和远程仓库是两个独立的仓库时,会出现错误:fatal: refusing to merge unrelated histories,此时需加上参数--allow-unrelated-histories
。
git push
推送到远程仓库。并不会推送标签。如使用--force或-f,则强制推送,可能会导致远程仓库已有的提交丢失:
git push [REMOTE] [[COMMIT:]REMOTEBRANCH] [--force|-f]
如出现如下错误,则在远程仓库执行git config --bool core.bare true
。
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
推送所有分支到远程仓库:
git push --all [REMOTE]
推送的时候同时在远程仓库创建分支:
git push -u|--set-upstream REMOTE REMOTEBRANCH
在远程仓库删除分支:
git push REMOTE --delete REMOTEBRANCH
推送标签到远程仓库:
git push REMOTE TAG
推送所有标签到远程仓库:
git push REMOTE --tags
删除远程仓库的标签:
git push REMOTE :refs/tags/TAG
git rebase
不要对在你的仓库外有副本的分支执行变基。变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。
变基。将当前分支变基到目标基底分支BRANCH,并应用当前分支相较于最近共同祖先的修改。一般这样做的目的是为了向远程分支推送时保持提交历史的整洁:
git rebase BRANCH
将特性分支BRANCHFROM变基到目标基底分支BRANCHTO:
git rebase BRANCHTO BRANCHFROM
取出BRANCHFROM分支,找出BRANCHFROM和BRANCHBASE共同祖先之后的修改,然后在BRANCHTO分支上重放:
git rebase --onto BRANCHTO BRANCHBASE BRANCHFROM
交互式变基,将指定提交及之后的提交重写:
git rebase -i COMMIT
其列出的提交历史是从旧至新的,修改提交历史前的命令,退出后git commit --amend
修改edit
命令指定的提交,git rebase --continue
自动应用剩余的提交。
中断变基:
git rebase --abort
如有变基冲突,需使用git mergetool
解决,然后执行git add
和git commit
。
处理完当前提交的变基冲突后,继续执行后续提交的变基:
git rebase --continue
git reflog
查看引用日志,引用日志只保存在本地仓库,且只会保存一段时间:
git reflog
git remote
查看本地仓库的远程仓库信息:
git remote [-v]
git remote show REMOTE
添加远程仓库:
git remote add SHORTNAME URL
重命名远程仓库:
git remote rename OLDNAME NEWNAME
移除远程仓库:
git remote rm REMOTE
git replace
替换提交。
git rerere
重用记录的解决方案(reuse recorded resolution)。
git reset
恢复暂存区,但不改变工作区,相当于回滚git add
:
git reset [NAME]
将HEAD指针、当前分支恢复至指定的提交,但不改变暂存区和工作区,相当于回滚git commit
:
git reset --soft COMMIT [NAME]
将HEAD指针、当前分支、暂存区恢复至指定的提交,但不改变工作区,相当于回滚git add
和git commit
:
git reset [--mixed] COMMIT [NAME]
将HEAD指针、当前分支、暂存区、工作区恢复到指定的提交,如工作区有未提交的内容则会丢失:
git reset --hard COMMIT [NAME]
交互式恢复:
git reset --patch
git rev-parse
解析提交的完整哈希:
git rev-parse BRANCH
git revert
撤销指定提交的所有改动,会创建一个新提交:
git revert COMMIT
还原至合并前:
git revert [-m N] HEAD
N的值:1为还原至本地分支,2为还原至待合入分支。
git rm
从暂存区移除跟踪文件,并从工作区删除文件。若文件已修改且已放入暂存区,则需要使用-f:
git rm [-f] NAME[ ...]
只从暂存区移除跟踪文件,不从工作区删除文件:
git rm --cached NAME[ ...]
git show
查看提交的变更内容:
git show [COMMIT] [FILENAME]
查看提交中指定文件的完整内容:
git show [COMMIT]:FILENAME
查看提交的简略统计信息:
git show --stat [COMMIT]
查看提交中发生变化的文件:
git show --name-only [COMMIT]
查看合并冲突的文件内容:
git show :N:FILENAME
N的值:1为共同祖先;2为当前分支;3为待合入的分支。
git stash
储藏改动:
git stash
git stash push [-m MSG]
还可以同时使用以下参数:
- -a或--all:同时储藏未跟踪的文件和忽略跟踪的文件。
- --include-untracked或-u:同时贮藏未跟踪的文件,但不包括忽略跟踪的文件。
- --keep-index:不仅贮藏已暂存的文件,还将它们保留在索引中。
交互式部分储藏改动,可输入以下子命令:
git stash push -p|--patch
- y:暂存此块文件内容。
- n:不暂存此块文件内容。
- q:退出且不暂存此块及所有文件余下的内容。
- a:暂存此块及本文件中所有后续块的文件内容。
- d:不暂存此块及本文件中所有后续块的文件内容。
- s:将当前块分割成更小的块。
- e:手工编辑当前块。
- ?:查看帮助。
查看储藏栈,每条以stash@{N}标记,stash@{0}为栈顶,即最近的储藏:
git stash list
应用栈顶的储藏后移除该储藏。可以在一个不干净的工作区,或其它分支上应用储藏,但可能产生合并冲突:
git stash pop [--index]
应用储藏,如不指定储藏标记,则默认应用最近的储藏。可以在一个不干净的工作区,或其它分支上应用储藏,但可能产生合并冲突:
git stash apply [--index] [stash@{N}]
使用--index可同时应用暂存,否则只应用文件的改动,不会重新暂存。
移除储藏:
git stash drop stash@{N}
从储藏创建分支:
git stash branch BRANCH [stash@{N}]
git status
查看当前文件状态。path可使用glob模式匹配:
git status [path]
默认只输出未跟踪文件的目录,如需同时输出未跟踪文件:
git status -u [path]
查看简短的输出:
git status [-s|--short] [path]
输出含义如下:
- ??:未跟踪。
- A:新跟踪到暂存区。
- 右M:已修改但未放入暂存区。
- M左:已修改并放入暂存区。
git submodule
使用子模块。
git tag
查看已有的标签,包括附注标签和轻量标签。以字母顺序列出:
git tag [-l GLOB]
创建轻量标签(lightweight):
git tag TAG [COMMIT]
创建附注标签(annotated):
git tag -a TAG -m MSG [COMMIT]
删除标签:
git tag -d TAG