Git
English ▾ 主題 ▾ 最新版本 ▾ git-svn 最後更新於 2.47.0

名稱

git-svn - Subversion 儲存庫與 Git 之間的雙向操作

概要

git svn <command> [<options>] [<arguments>]

描述

git svn 是 Subversion 和 Git 之間變更集的簡單管道。它提供 Subversion 和 Git 儲存庫之間的雙向變更流。

git svn 可以追蹤標準的 Subversion 儲存庫,遵循常見的「trunk/branches/tags」佈局,使用 --stdlayout 選項。它也可以使用 -T/-t/-b 選項追蹤任何佈局中的分支和標籤(請參閱下方 init 的選項,以及 clone 命令)。

一旦追蹤 Subversion 儲存庫(使用上述任何方法),可以使用 fetch 命令從 Subversion 更新 Git 儲存庫,並使用 dcommit 命令從 Git 更新 Subversion。

命令

init

初始化一個空的 Git 儲存庫,其中包含 git svn 的額外元數據目錄。Subversion URL 可以指定為命令列參數,或作為 -T/-t/-b 的完整 URL 參數。或者,可以指定要操作的目標目錄作為第二個參數。通常,此命令會初始化目前目錄。

-T<trunk-subdir>
--trunk=<trunk-subdir>
-t<tags-subdir>
--tags=<tags-subdir>
-b<branches-subdir>
--branches=<branches-subdir>
-s
--stdlayout

這些是 init 的選用命令列選項。每個標誌都可以指向相對儲存庫路徑(--tags=project/tags)或完整 URL(--tags=https://foo.org/project/tags)。您可以指定多個 --tags 和/或 --branches 選項,以防您的 Subversion 儲存庫將標籤或分支放置在多個路徑下。--stdlayout 選項是將 trunk、tags、branches 設定為相對路徑的簡寫方式,這是 Subversion 的預設值。如果也給定任何其他選項,它們將優先。

--no-metadata

在 [svn-remote] 設定中設定 noMetadata 選項。不建議使用此選項,請在使用此選項之前閱讀此手冊頁的 svn.noMetadata 區段。

--use-svm-props

在 [svn-remote] 設定中設定 useSvmProps 選項。

--use-svnsync-props

在 [svn-remote] 設定中設定 useSvnsyncProps 選項。

--rewrite-root=<URL>

在 [svn-remote] 設定中設定 rewriteRoot 選項。

--rewrite-uuid=<UUID>

在 [svn-remote] 設定中設定 rewriteUUID 選項。

--username=<user>

對於 SVN 處理驗證的傳輸(http、https 和純 svn),請指定使用者名稱。對於其他傳輸(例如 svn+ssh://),您必須在 URL 中包含使用者名稱,例如 svn+ssh://foo@svn.bar.com/project

--prefix=<prefix>

這允許指定前綴,如果指定 trunk/branches/tags,則該前綴會附加到遠端名稱。前綴不會自動包含尾隨斜線,因此請確保在您需要的情況下在參數中包含一個斜線。如果指定 --branches/-b,則前綴必須包含尾隨斜線。在任何情況下都強烈建議設定前綴(帶有尾隨斜線),因為您的 SVN 追蹤參考將位於「refs/remotes/$prefix/**」,這與 Git 自己的遠端追蹤參考佈局(refs/remotes/$remote/**)相容。如果您希望追蹤共用通用儲存庫的多個專案,設定前綴也很有用。預設情況下,前綴設定為 origin/

注意
在 Git v2.0 之前,預設前綴為 ""(無前綴)。這表示 SVN 追蹤參考放置在「refs/remotes/*」,這與 Git 自己的遠端追蹤參考的組織方式不相容。如果您仍然想要舊的預設值,您可以在命令列上傳遞 --prefix "" 來取得它(如果您的 Perl 的 Getopt::Long 版本 < v2.37,--prefix="" 可能無法運作)。
--ignore-refs=<regex>

當傳遞給 initclone 時,此正規表示式將保留為設定鍵。請參閱 fetch 以取得 --ignore-refs 的描述。

--ignore-paths=<regex>

當傳遞給 initclone 時,此正規表示式將保留為設定鍵。請參閱 fetch 以取得 --ignore-paths 的描述。

--include-paths=<regex>

當傳遞給 initclone 時,此正規表示式將保留為設定鍵。請參閱 fetch 以取得 --include-paths 的描述。

--no-minimize-url

當追蹤多個目錄(使用 --stdlayout、--branches 或 --tags 選項)時,git svn 將嘗試連線到 Subversion 儲存庫的根目錄(或允許的最高層級)。如果整個專案在儲存庫中移動,此預設值允許更好地追蹤歷史記錄,但可能會在實施讀取權限限制的儲存庫上造成問題。傳遞 --no-minimize-url 將允許 git svn 接受 URL,而不嘗試連線到更高層級的目錄。預設情況下,僅追蹤一個 URL/分支時,此選項為關閉(它幾乎沒有作用)。

fetch

從我們追蹤的 Subversion 遠端提取尚未提取的修訂版本。可以指定 $GIT_DIR/config 檔案中 [svn-remote "…​"] 區段的名稱作為選用的命令列參數。

如果需要,這會自動更新 rev_map(請參閱下方 FILES 區段中的 $GIT_DIR/svn/**/.rev_map.* 以了解詳細資訊)。

--localtime

將 Git 提交時間儲存在本地時區,而不是 UTC。這使得 git log(即使沒有 --date=local)顯示與本地時區的 svn log 相同的時間。

這不會干擾與您複製的 Subversion 儲存庫的互通性,但如果您希望您的本地 Git 儲存庫能夠與其他人的本地 Git 儲存庫互通,則不要使用此選項,或者您們都應該在相同的本地時區中使用它。

--parent

僅從目前 HEAD 的 SVN 上層提取。

--ignore-refs=<regex>

忽略符合 Perl 正規表示式分支或標籤的參考。「負向後行斷言」如 ^refs/remotes/origin/(?!tags/wanted-tag|wanted-branch).*$ 可用於僅允許特定參考。

config key: svn-remote.<name>.ignore-refs

如果設定了 ignore-refs 設定鍵,並且也給定了命令列選項,則將使用兩個正規表示式。

--ignore-paths=<regex>

這允許您指定一個 Perl 正規表示式,該表示式將導致從 SVN 提取時略過所有符合路徑。--ignore-paths 選項應在給定儲存庫上的每個 fetch(包括由於 clonedcommitrebase 等引起的自動提取)都符合。

config key: svn-remote.<name>.ignore-paths

如果設定了 ignore-paths 設定鍵,並且也給定了命令列選項,則將使用兩個正規表示式。

範例

每次提取都跳過「doc*」目錄
--ignore-paths="^doc"
跳過第一層目錄的「branches」和「tags」
--ignore-paths="^[^/]+/(?:branches|tags)"
--include-paths=<regex>

這允許您指定一個 Perl 正規表示式,該表示式將導致僅包含從 SVN 提取時符合的路徑。--include-paths 選項應在給定儲存庫上的每個 fetch(包括由於 clonedcommitrebase 等引起的自動提取)都符合。--ignore-paths 的優先順序高於 --include-paths

config key: svn-remote.<name>.include-paths
--log-window-size=<n>

掃描 Subversion 歷史記錄時,每個請求擷取 <n> 個日誌條目。預設值為 100。對於非常大的 Subversion 儲存庫,可能需要較大的值才能在合理的時間內完成clone/fetch。但是過大的值可能會導致更高的記憶體使用量和請求超時。

clone

執行 initfetch。它會根據傳遞給它的 URL 的基本名稱自動建立一個目錄;或者如果傳遞了第二個參數,它將建立一個目錄並在其中工作。它接受 initfetch 命令接受的所有參數;但 --fetch-all--parent 除外。在儲存庫被複製後,fetch 命令將能夠更新修訂版本,而不會影響工作樹;而 rebase 命令將能夠使用最新的更改更新工作樹。

--preserve-empty-dirs

在本地 Git 儲存庫中,為從 Subversion 擷取的每個空目錄建立一個佔位符檔案。這包括通過移除 Subversion 儲存庫中的所有條目(但不是目錄本身)而變為空的目錄。佔位符檔案也會被追蹤,並在不再需要時被移除。

--placeholder-filename=<filename>

設定 --preserve-empty-dirs 建立的佔位符檔案的名稱。預設值:".gitignore"

rebase

這會從目前 HEAD 的 SVN 父節點擷取修訂版本,並將目前(未提交到 SVN)的工作基於它進行 rebase。

它的運作方式類似於 svn updategit pull,不同之處在於它使用 git rebase 而不是 git merge 來保留線性歷史記錄,以便更容易使用 git svn 進行 dcommit。

它接受 git svn fetchgit rebase 接受的所有選項。但是,--fetch-all 只會從目前的 [svn-remote] 擷取,而不會從所有 [svn-remote] 定義擷取。

git rebase 類似;這要求工作樹必須是乾淨的,且沒有未提交的變更。

如果需要,這會自動更新 rev_map(請參閱下方 FILES 區段中的 $GIT_DIR/svn/**/.rev_map.* 以了解詳細資訊)。

-l
--local

不要從遠端擷取;僅針對來自上游 SVN 的最後擷取的提交執行 git rebase

dcommit

將目前分支的每個差異直接提交到 SVN 儲存庫,然後重新基底或重設(取決於 SVN 和 head 之間是否存在差異)。這會在 Git 中的每次提交中建立一個 SVN 修訂版本。

當指定一個可選的 Git 分支名稱(或 Git 提交物件名稱)作為參數時,子命令會對指定的分支執行操作,而不是對目前分支執行操作。

建議使用 dcommit 而不是 set-tree(如下)。

--no-rebase

提交後,不要重新基底或重設。

--commit-url <URL>

提交到此 SVN URL(完整路徑)。這旨在允許重複使用使用一種傳輸方法(例如,匿名讀取的 svn://http://)建立的現有 git svn 儲存庫,如果稍後給予使用者使用替代傳輸方法(例如,用於提交的 svn+ssh://https://)的權限。

config key: svn-remote.<name>.commiturl
config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)

請注意,commiturl 組態鍵的 SVN URL 包含 SVN 分支。如果您希望為整個 SVN 儲存庫設定提交 URL,請改用 svn-remote.<name>.pushurl。

強烈不建議將此選項用於任何其他目的(不要問)。

--mergeinfo=<mergeinfo>

在 dcommit 期間新增給定的合併資訊(例如,--mergeinfo="/branches/foo:1-10")。所有 svn 伺服器版本都可以儲存此資訊(作為屬性),且從 1.5 版開始的 svn 用戶端可以使用它。若要指定來自多個分支的合併資訊,請在分支之間使用單個空格字元(--mergeinfo="/branches/foo:1-10 /branches/bar:3,5-6,8"

config key: svn.pushmergeinfo

此選項將使 git-svn 嘗試在可能的情況下自動在 SVN 儲存庫中填入 svn:mergeinfo 屬性。目前,只有在 dcommit 非快轉合併,且所有父節點(第一個除外)都已推送至 SVN 時,才能執行此操作。

--interactive

要求使用者確認是否應將修補程式集實際傳送至 SVN。對於每個修補程式,可以回答「yes」(接受此修補程式)、「no」(捨棄此修補程式)、「all」(接受所有修補程式)或「quit」。

如果答案是「no」或「quit」,git svn dcommit 會立即返回,而不會將任何內容提交至 SVN。

branch

在 SVN 儲存庫中建立分支。

-m
--message

允許指定提交訊息。

-t
--tag

透過使用在 git svn init 期間指定的 tags_subdir 而不是 branches_subdir 來建立標籤。

-d<path>
--destination=<path>

如果給 initclone 命令指定了多個 --branches(或 --tags)選項,則必須提供您想要在 SVN 儲存庫中建立的分支(或標籤)的位置。<path> 指定用於建立分支或標籤的路徑,並且應與其中一個已設定的分支或標籤 refspec 的左側模式相符。您可以使用以下命令查看這些 refspec

git config --get-all svn-remote.<name>.branches
git config --get-all svn-remote.<name>.tags

其中 <name> 是 init 的 -R 選項所指定的 SVN 儲存庫名稱(或預設為 "svn")。

--username

指定執行提交的 SVN 使用者名稱。此選項會覆寫 username 組態屬性。

--commit-url

使用指定的 URL 連線至目標 Subversion 儲存庫。這在來源 SVN 儲存庫是唯讀的情況下非常有用。此選項會覆寫組態屬性 commiturl

git config --get-all svn-remote.<name>.commiturl
--parents

建立父資料夾。此參數等同於 svn cp 命令的 --parents 參數,並且適用於非標準的儲存庫配置。

tag

在 SVN 儲存庫中建立標籤。這是 branch -t 的簡寫。

log

當 svn 使用者提到 -r/--revision 編號時,這應該可以讓您輕鬆查閱 svn 日誌訊息。

支援 ‘svn log’ 的以下功能

-r <n>[:<n>]
--revision=<n>[:<n>]

受支援,非數字引數不受支援:HEAD、NEXT、BASE、PREV 等…

-v
--verbose

它與 svn 日誌中的 --verbose 輸出不完全相容,但相當接近。

--limit=<n>

與 --max-count 不同,不計算合併/排除的提交

--incremental

支援

新功能

--show-commit

同時顯示 Git 提交 sha1

--oneline

我們的 --pretty=oneline 版本

注意
SVN 本身僅以 UTC 格式儲存時間,而不儲存其他資訊。常規 svn 用戶端會將 UTC 時間轉換為本地時間(或根據 TZ= 環境)。此命令具有相同的行為。

任何其他引數都會直接傳遞給 git log

blame

顯示上次修改檔案中每一行的修訂版本和作者。預設情況下,此模式的輸出在格式上與 ‘svn blame’ 的輸出相容。與 SVN blame 命令類似,會忽略工作樹中未提交的本機變更;會註解 HEAD 修訂版本中的檔案版本。未知的引數會直接傳遞給 git blame

--git-format

以與 git blame 相同的格式產生輸出,但使用 SVN 修訂版本號碼而不是 Git 提交雜湊。在此模式下,尚未提交至 SVN 的變更(包括本機工作副本編輯)會顯示為修訂版本 0。

find-rev

當給定形式為 rN 的 SVN 修訂版本號碼時,會傳回對應的 Git 提交雜湊(這後面可以選擇加上樹狀物件,以指定應搜尋哪個分支)。當給定樹狀物件時,會傳回對應的 SVN 修訂版本號碼。

-B
--before

如果給定 SVN 修訂版本,則不要求完全符合,而是尋找與指定修訂版本時的 SVN 儲存庫狀態(在目前分支上)相對應的提交。

-A
--after

如果給定 SVN 修訂版本,則不要求完全符合;如果沒有完全符合的項目,則傳回在歷史記錄中向前搜尋的最接近的符合項目。

set-tree

您應該考慮使用 dcommit 而不是此命令。將指定的提交或樹狀物件提交至 SVN。這取決於您匯入的擷取資料是否為最新。這絕對不會嘗試在提交至 SVN 時執行修補作業,它只會使用樹狀物件或提交中指定的內容覆寫檔案。所有合併都假設已獨立於 git svn 函數進行。

create-ignore

遞迴尋找目錄上的 svn:ignore 和 svn:global-ignores 屬性,並建立相符的 .gitignore 檔案。產生的檔案會被暫存以進行提交,但不會被提交。使用 -r/--revision 來參照特定的修訂版本。

show-ignore

遞迴尋找並列出目錄上的 svn:ignore 和 svn:global-ignores 屬性。輸出適用於附加到 $GIT_DIR/info/exclude 檔案。

mkdirs

嘗試根據 $GIT_DIR/svn/<refname>/unhandled.log 檔案中的資訊,重新建立核心 Git 無法追蹤的空目錄。使用 "git svn clone" 和 "git svn rebase" 時,會自動重新建立空目錄,因此 "mkdirs" 適用於在執行 "git checkout" 或 "git reset" 等命令後使用。(如需更多資訊,請參閱 svn-remote.<name>.automkdirs 組態檔案選項。)

commit-diff

從命令列提交兩個樹狀物件引數的差異。此命令不依賴於是否在 git svn init 初始化的儲存庫內。此命令接受三個引數,(a) 用於比對差異的原始樹狀物件、(b) 新樹狀物件結果、(c) 目標 Subversion 儲存庫的 URL。如果您從具有 git svn 感知的儲存庫(已使用 git svn 進行 init)工作,則可以省略最後一個引數(URL)。此操作需要 -r<revision> 選項。

提交訊息可直接使用 -m-F 選項提供,或間接從標籤或提交提供(當第二個樹狀物件表示這類物件時),或透過叫用編輯器要求提供(請參閱下方的 --edit 選項)。

-m <msg>
--message=<msg>

使用給定的 msg 作為提交訊息。此選項會停用 --edit 選項。

-F <filename>
--file=<filename>

從給定的檔案中取得提交訊息。此選項會停用 --edit 選項。

info

顯示關於檔案或目錄的資訊,類似於 ‘svn info’ 提供的資訊。目前不支援 -r/--revision 參數。使用 --url 選項只輸出 URL: 欄位的值。

proplist

列出儲存在 Subversion 儲存庫中,關於指定檔案或目錄的屬性。使用 -r/--revision 來參考特定的 Subversion 修訂版本。

propget

取得指定檔案的第一個參數所提供的 Subversion 屬性。可以使用 -r/--revision 指定特定的修訂版本。

propset

將第一個參數所提供的 Subversion 屬性,設定為第二個參數所提供的值,適用於第三個參數所提供的檔案。

範例

git svn propset svn:keywords "FreeBSD=%H" devel/py-tipper/Makefile

這會將 svn:keywords 屬性設定為 FreeBSD=%H,適用於 devel/py-tipper/Makefile 檔案。

show-externals

顯示 Subversion 的外部參照。使用 -r/--revision 來指定特定的修訂版本。

gc

壓縮 $GIT_DIR/svn/<refname>/unhandled.log 檔案,並移除 $GIT_DIR/svn/<refname>/index 檔案。

reset

fetch 的效果還原到指定的修訂版本。這允許您重新 fetch 一個 SVN 修訂版本。通常 SVN 修訂版本的內容不應該變更,因此 reset 應該是不必要的。但是,如果 SVN 權限變更,或者如果您變更了 --ignore-paths 選項,fetch 可能會失敗並顯示「在提交中找不到」(檔案之前不可見) 或「校驗和不符」(錯過修改)。如果無法永久忽略問題檔案 (使用 --ignore-paths),則修復儲存庫的唯一方法是使用 reset

只有 rev_map 和 refs/remotes/git-svn 會被變更 (請參閱下面 FILES 章節中的 $GIT_DIR/svn/**/.rev_map.* 了解詳細資訊)。在 reset 之後,接著執行 fetch,然後使用 git resetgit rebase 將本機分支移動到新的樹狀結構上。

-r <n>
--revision=<n>

指定要保留的最新修訂版本。所有後續的修訂版本都會被捨棄。

-p
--parent

同時捨棄指定的修訂版本,改為保留最近的父修訂版本。

範例

假設您在 "master" 分支中有本機變更,但是您需要重新 fetch "r2"。

    r1---r2---r3 remotes/git-svn
                \
                 A---B master

修正導致 "r2" 不完整的 ignore-paths 或 SVN 權限問題。然後

git svn reset -r2 -p
git svn fetch
    r1---r2'--r3' remotes/git-svn
      \
       r2---r3---A---B master

然後使用 git rebase 修復 "master"。請勿使用 git merge,否則您的歷史記錄將無法與未來 dcommit 相容!

git rebase --onto remotes/git-svn A^ master
    r1---r2'--r3' remotes/git-svn
                \
                 A'--B' master

選項

--shared[=(false|true|umask|group|all|world|everybody)]
--template=<template-directory>

僅用於 init 命令。這些選項會直接傳遞給 git init

-r <arg>
--revision <arg>

用於 fetch 命令。

這允許支援用於部分/受限制歷史記錄的修訂版本範圍。支援 $NUMBER、$NUMBER1:$NUMBER2 (數值範圍)、$NUMBER:HEAD 和 BASE:$NUMBER。

這可以讓您在執行 fetch 時建立部分鏡像,但通常不建議這樣做,因為會略過歷史記錄並遺失。

-
--stdin

僅用於 set-tree 命令。

從 stdin 讀取提交列表,並以相反的順序提交它們。僅從每行讀取開頭的 sha1,因此可以使用 git rev-list --pretty=oneline 的輸出。

--rmdir

僅用於 dcommitset-treecommit-diff 命令。

如果 SVN 樹狀結構中沒有剩餘的檔案,則移除目錄。SVN 可以為空目錄建立版本,如果目錄中沒有剩餘的檔案,預設不會移除它們。Git 無法為空目錄建立版本。啟用此標誌將使對 SVN 的提交行為像 Git 一樣。

config key: svn.rmdir
-e
--edit

僅用於 dcommitset-treecommit-diff 命令。

在提交到 SVN 之前編輯提交訊息。對於提交的物件,此選項預設為關閉,而在提交樹狀結構物件時則強制開啟。

config key: svn.edit
-l<num>
--find-copies-harder

僅用於 dcommitset-treecommit-diff 命令。

它們都會直接傳遞給 git diff-tree;請參閱 git-diff-tree[1] 以取得更多資訊。

config key: svn.l
config key: svn.findcopiesharder
-A<filename>
--authors-file=<filename>

語法與 git cvsimport 使用的檔案相容,但可以使用 <> 提供空的電子郵件地址。

	loginname = Joe User <user@example.com>

如果指定此選項,且 git svn 遇到作者檔案中不存在的 SVN 提交者名稱,則 git svn 將中止操作。然後,使用者必須加入適當的項目。修改作者檔案後重新執行先前的 git svn 命令應該可以繼續操作。

config key: svn.authorsfile
--authors-prog=<filename>

如果指定此選項,對於作者檔案中不存在的每個 SVN 提交者名稱,將會執行給定的檔案,並將提交者名稱作為第一個參數。該程式預期會傳回單行格式為 "Name <email>" 或 "Name <>" 的文字,這將被視為已包含在作者檔案中。

由於歷史因素,相對於目前目錄,會先搜尋相對的 filename 以用於 initclone,而相對於工作樹的根目錄,則會先搜尋相對的 filename 以用於 fetch。如果找不到 filename,則會在 $PATH 中像任何其他命令一樣搜尋。

config key: svn.authorsProg
-q
--quiet

git svn 的輸出減少。指定第二次會讓輸出更少。

-m
--merge
-s<strategy>
--strategy=<strategy>
-p
--rebase-merges

這些選項僅用於 dcommitrebase 命令。

當使用 dcommit 時,如果無法使用 git reset (請參閱 dcommit),則會直接傳遞給 git rebase

-n
--dry-run

這可以用於 dcommitrebasebranchtag 命令。

對於 dcommit,列印出將會顯示哪些差異會提交到 SVN 的 Git 參數序列。

對於 rebase,顯示與目前分支關聯的上游 SVN 儲存庫,以及將從中 fetch 的 SVN 儲存庫 URL。

對於 branchtag,顯示在建立分支或標籤時將用於複製的 URL。

--use-log-author

當將 SVN 提交擷取到 Git 中 (作為 fetchrebasedcommit 操作的一部分) 時,請在記錄訊息中尋找第一個 From: 行或 Signed-off-by 結尾,並將其用作作者字串。

config key: svn.useLogAuthor
--add-author-from

當從 Git 提交到 SVN 時 (作為 set-treedcommit 操作的一部分),如果現有的記錄訊息中沒有 From:Signed-off-by 結尾,則根據 Git 提交的作者字串附加 From: 行。如果您使用此選項,則 --use-log-author 將會為所有提交擷取有效的作者字串。

config key: svn.addAuthorFrom

進階選項

-i<GIT_SVN_ID>
--id <GIT_SVN_ID>

這會設定 GIT_SVN_ID (而不是使用環境變數)。這允許使用者覆寫追蹤單一 URL 時要 fetch 的預設 refname。logdcommit 命令不再需要此切換作為參數。

-R<remote-name>
--svn-remote <remote-name>

指定要使用的 [svn-remote "<remote-name>"] 區段,這允許追蹤多個 SVN 儲存庫。預設值:「svn」

--follow-parent

只有在我們追蹤分支時,此選項才相關 (使用其中一個儲存庫版面配置選項 --trunk、--tags、--branches、--stdlayout)。對於每個追蹤的分支,嘗試找出其修訂版本複製來源,並在分支的第一次 Git 提交中設定合適的父系。當我們追蹤儲存庫中已移動的目錄時,這特別有用。如果停用此功能,git svn 建立的分支將會是線性的,並且不會共享任何歷史記錄,這表示不會有關於分支在哪裡分支或合併的資訊。但是,追蹤冗長/複雜的歷史記錄可能需要很長時間,因此停用此功能可能會加速複製過程。此功能預設為啟用,使用 --no-follow-parent 來停用它。

config key: svn.followparent

僅限設定檔選項

svn.noMetadata
svn-remote.<name>.noMetadata

這會移除每個提交結尾的 git-svn-id: 行。

此選項只能用於一次性匯入,因為如果沒有中繼資料,git svn 將無法再次 fetch。此外,如果您遺失 $GIT_DIR/svn/**/.rev_map.* 檔案,git svn 將無法重建它們。

git svn log 命令也無法在使用了此選項的儲存庫上運作。使用此選項與 useSvmProps 選項衝突 (希望原因很明顯)。

不建議使用此選項,因為它很難在現有文件、錯誤報告和歸檔中追蹤到 SVN 修訂號碼的舊參照。如果您計劃最終從 SVN 遷移到 Git,並且確定要放棄 SVN 歷史記錄,請考慮使用 git-filter-repo。filter-repo 也允許重新格式化中繼資料以方便閱讀,並為非 "svn.authorsFile" 使用者重寫作者資訊。

svn.useSvmProps
svn-remote.<name>.useSvmProps

這讓 git svn 可以重新映射使用 SVN::Mirror (或 svk) 建立的鏡像的儲存庫 URL 和 UUID 以取得元數據。

如果 SVN 修訂版具有 "svm:headrev" 屬性,則該修訂版很可能是由 SVN::Mirror(也由 SVK 使用)建立的。該屬性包含儲存庫 UUID 和修訂版。我們希望讓它看起來像是正在鏡像原始 URL,因此引入一個輔助函數,該函數會返回原始的身分 URL 和 UUID,並在產生提交訊息中的元數據時使用它。

svn.useSvnsyncProps
svn-remote.<名稱>.useSvnsyncprops

與 useSvmProps 選項類似;這是為了使用 SVN 1.4.x 及更高版本隨附的 svnsync(1) 命令的使用者。

svn-remote.<名稱>.rewriteRoot

這允許使用者從替代 URL 建立儲存庫。例如,管理員可以在本機伺服器上執行 git svn (透過 file:// 存取),但希望在元數據中以公用 http:// 或 svn:// URL 分發儲存庫,以便其使用者會看到公用 URL。

svn-remote.<名稱>.rewriteUUID

與 useSvmProps 選項類似;這是為了需要手動重新映射 UUID 的使用者。在無法透過 useSvmProps 或 useSvnsyncProps 取得原始 UUID 的情況下,這可能很有用。

svn-remote.<名稱>.pushurl

與 Git 的 remote.<名稱>.pushurl 類似,此金鑰旨在用於 url 透過唯讀傳輸指向 SVN 儲存庫的情況,以提供替代的讀/寫傳輸。假設兩個金鑰都指向同一個儲存庫。與 commiturl 不同,pushurl 是基本路徑。如果可以使用 commiturlpushurl,則 commiturl 優先。

svn.brokenSymlinkWorkaround

這會停用潛在的昂貴檢查,以解決由損壞的客戶端簽入 SVN 的損壞符號連結。如果您追蹤具有許多不是符號連結的空 blob 的 SVN 儲存庫,請將此選項設定為 "false"。此選項可以在 git svn 執行時變更,並在下一個擷取的修訂版生效。如果未設定,git svn 假設此選項為 "true"。

svn.pathnameencoding

這會指示 git svn 將路徑名稱重新編碼為給定的編碼。Windows 使用者和在非 utf8 地區工作的使用者可以使用它來避免具有非 ASCII 字元的損壞檔案名稱。有效的編碼是 Perl 的 Encode 模組支援的編碼。

svn-remote.<名稱>.automkdirs

通常,"git svn clone" 和 "git svn rebase" 命令會嘗試重新建立 Subversion 儲存庫中的空目錄。如果此選項設定為 "false",則只有在明確執行 "git svn mkdirs" 命令時才會建立空目錄。如果未設定,git svn 假設此選項為 "true"。

由於 noMetadata、rewriteRoot、rewriteUUID、useSvnsyncProps 和 useSvmProps 選項都會影響 git svn 產生和使用的元數據;它們必須在匯入任何歷史記錄之前在設定檔中設定,而且一旦設定這些設定就不應變更。

此外,每個 svn-remote 區段只能使用這些選項中的一個,因為它們會影響 git-svn-id: 元數據行,除了 rewriteRoot 和 rewriteUUID 可以一起使用之外。

基本範例

追蹤和貢獻到 Subversion 管理專案的主幹(忽略標籤和分支)

# Clone a repo (like git clone):
	git svn clone http://svn.example.com/project/trunk
# Enter the newly cloned directory:
	cd trunk
# You should be on master branch, double-check with 'git branch'
	git branch
# Do some work and commit locally to Git:
	git commit ...
# Something is committed to SVN, rebase your local changes against the
# latest changes in SVN:
	git svn rebase
# Now commit your changes (that were committed previously using Git) to SVN,
# as well as automatically updating your working HEAD:
	git svn dcommit
# Append svn:ignore and svn:global-ignores settings to the default Git exclude file:
	git svn show-ignore >> .git/info/exclude

追蹤和貢獻到整個 Subversion 管理的專案(包含主幹、標籤和分支)

# Clone a repo with standard SVN directory layout (like git clone):
	git svn clone http://svn.example.com/project --stdlayout --prefix svn/
# Or, if the repo uses a non-standard directory layout:
	git svn clone http://svn.example.com/project -T tr -b branch -t tag --prefix svn/
# View all branches and tags you have cloned:
	git branch -r
# Create a new branch in SVN
	git svn branch waldo
# Reset your master to trunk (or any other branch, replacing 'trunk'
# with the appropriate name):
	git reset --hard svn/trunk
# You may only dcommit to one branch/tag/trunk at a time.  The usage
# of dcommit/rebase/show-ignore should be the same as above.

初始的 git svn clone 可能相當耗時(特別是對於大型 Subversion 儲存庫)。如果多個人(或一人擁有多台電腦)想要使用 git svn 來與同一個 Subversion 儲存庫互動,您可以在伺服器上對儲存庫執行初始的 git svn clone,並讓每個人都使用 git clone 來複製該儲存庫

# Do the initial import on a server
	ssh server "cd /pub && git svn clone http://svn.example.com/project [options...]"
# Clone locally - make sure the refs/remotes/ space matches the server
	mkdir project
	cd project
	git init
	git remote add origin server:/pub/project
	git config --replace-all remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
	git fetch
# Prevent fetch/pull from remote Git server in the future,
# we only want to use git svn for future updates
	git config --remove-section remote.origin
# Create a local branch from one of the branches just fetched
	git checkout -b master FETCH_HEAD
# Initialize 'git svn' locally (be sure to use the same URL and
# --stdlayout/-T/-b/-t/--prefix options as were used on server)
	git svn init http://svn.example.com/project [options...]
# Pull the latest changes from Subversion
	git svn rebase

變基與拉取/合併

偏好使用 git svn rebasegit rebase,而不是 git pullgit merge 來同步未整合的提交與 git svn 分支。這樣做會使未整合提交的歷史記錄相對於上游 SVN 儲存庫保持線性,並允許使用偏好的 git svn dcommit 子命令將未整合的提交推送回 SVN。

最初,git svn 建議開發人員從 git svn 分支拉取或合併。這是因為作者偏好使用 git svn set-tree B 來提交單一 head,而不是使用 git svn set-tree A..B 標記來提交多個提交。使用 git pullgit mergegit svn set-tree A..B 將導致在提交到 SVN 時,非線性的歷史記錄會被平坦化,這可能會導致合併提交意外地反轉 SVN 中先前的提交。

合併追蹤

雖然 git svn 可以追蹤採用標準版面配置的儲存庫的複製歷史記錄(包括分支和標籤),但它還無法將在 git 內部發生的合併歷史記錄表示回上游給 SVN 使用者。因此,建議使用者在 Git 內部盡可能保持歷史記錄的線性,以簡化與 SVN 的相容性(請參閱下方的「注意事項」一節)。

SVN 分支的處理

如果 git svn 設定為擷取分支 (而且 --follow-branches 生效),有時會為一個 SVN 分支建立多個 Git 分支,其中額外的分支具有 branchname@nnn 形式的名稱 (其中 nnn 是 SVN 修訂號)。如果 git svn 無法找到 SVN 分支中第一個提交的父提交,以將分支連接到其他分支的歷史記錄,則會建立這些額外的分支。

通常,SVN 分支中的第一個提交包含複製作業。git svn 會讀取此提交以取得建立分支的 SVN 修訂版。然後,它會嘗試尋找與此 SVN 修訂版對應的 Git 提交,並將其用作分支的父系。但是,可能沒有合適的 Git 提交可用作父系。如果 SVN 分支是未被 git svn 擷取的修訂版的複本(例如,因為它是使用 --revision 跳過的舊修訂版),或者如果在 SVN 中複製了未被 git svn 追蹤的目錄(例如完全未追蹤的分支,或追蹤分支的子目錄),則會發生這種情況。在這些情況下,git svn 仍會建立一個 Git 分支,但不會使用現有的 Git 提交作為分支的父系,而是會讀取複製分支的目錄的 SVN 歷史記錄,並建立適當的 Git 提交。這會由訊息「正在初始化父系:<branchname>」表示。

此外,它會建立一個名為 <branchname>@<SVN-Revision> 的特殊分支,其中 <SVN-Revision> 是複製分支的 SVN 修訂號。此分支將指向分支新建立的父提交。如果在 SVN 中刪除了分支,然後又從不同的版本重新建立,則會有許多具有 @ 的分支。

請注意,這可能表示會為單一 SVN 修訂版建立多個 Git 提交。

範例:在具有標準 trunk/tags/branches 版面配置的 SVN 儲存庫中,在 r.100 中建立目錄 trunk/sub。在 r.200 中,透過將其複製到 branches/ 來建立 trunk/sub 的分支。然後 git svn clone -s 將建立一個分支 sub。它也會為 r.100 到 r.199 建立新的 Git 提交,並將這些用作分支 sub 的歷史記錄。因此,對於 r.100 到 r.199 的每個修訂版,都會有兩個 Git 提交(一個包含 trunk/,另一個包含 trunk/sub/)。最後,它會建立一個分支 sub@200,指向分支 sub 的新父提交 (即 r.200 和 trunk/sub/ 的提交)。

注意事項

為了簡單起見並與 Subversion 互通,建議所有 git svn 使用者都直接從 SVN 伺服器複製、擷取和 dcommit,並避免 Git 儲存庫和分支之間的所有 git clone/pull/merge/push 作業。建議的在 Git 分支和使用者之間交換程式碼的方法是 git format-patchgit am,或僅對 SVN 儲存庫執行 'dcommit'。

不建議在您計畫從中進行 dcommit 的分支上執行 git mergegit pull,因為 Subversion 使用者看不到您所做的任何合併。此外,如果您從屬於 SVN 分支鏡像的 Git 分支合併或拉取,dcommit 可能會提交到錯誤的分支。

如果您進行合併,請注意以下規則:git svn dcommit 將嘗試提交到

git log --grep=^git-svn-id: --first-parent -1

因此,您必須確保您要 dcommit 的分支的最新提交是合併的第一個父系。否則會發生混亂,特別是如果第一個父系是同一個 SVN 分支上的舊提交。

git clone 不會複製 refs/remotes/ 階層下的分支或任何 git svn 元數據或設定。因此,如果要做複製,則使用 git svn 建立和管理的儲存庫應使用 rsync 進行複製。

由於 dcommit 在內部使用變基,因此您在執行 dcommit 之前使用 git push 到的任何 Git 分支都需要強制覆寫遠端儲存庫上的現有 ref。這通常被認為是不好的做法,請參閱 git-push[1] 文件以瞭解詳細資訊。

不要對您已 dcommit 的變更使用 git-commit[1] 的 --amend 選項。修改您已推送至其他使用者的遠端儲存庫的提交是不好的做法,而使用 SVN 的 dcommit 與此類似。

複製 SVN 儲存庫時,如果未使用任何描述儲存庫版面配置的選項 (–trunk、–tags、–branches、–stdlayout),則 git svn clone 將建立一個具有完全線性歷史記錄的 Git 儲存庫,其中分支和標籤會顯示為工作副本中的個別目錄。雖然這是取得完整儲存庫複本的最簡單方法,但對於具有許多分支的專案,它會導致工作副本比僅主幹大數倍。因此,對於使用標準目錄結構 (trunk/branches/tags) 的專案,建議使用 --stdlayout 選項進行複製。如果專案使用非標準結構,和/或如果不需要分支和標籤,則最簡單的方法是僅複製一個目錄(通常是主幹),而不提供任何儲存庫版面配置選項。如果需要包含分支和標籤的完整歷史記錄,則必須使用選項 --trunk / --branches / --tags

當使用多個 --branches 或 --tags 時,git svn 不會自動處理名稱衝突(例如,如果來自不同路徑的兩個分支具有相同的名稱,或者如果分支和標籤具有相同的名稱)。在這些情況下,請使用 init 來設定您的 Git 儲存庫,然後在您的第一次 fetch 之前,編輯 $GIT_DIR/config 檔案,以便分支和標籤與不同的命名空間相關聯。例如

branches = stable/*:refs/remotes/svn/stable/*
branches = debug/*:refs/remotes/svn/debug/*

設定

git svn 將 [svn-remote] 設定資訊儲存在儲存庫的 $GIT_DIR/config 檔案中。它類似於核心 Git 的 [remote] 區段,除了 fetch 鍵不接受 glob 引數;而是由 branchestags 鍵處理。由於某些 SVN 儲存庫的配置很奇怪,包含多個專案,因此允許使用下列列出的 glob 展開

[svn-remote "project-a"]
	url = http://server.org/svn
	fetch = trunk/project-a:refs/remotes/project-a/trunk
	branches = branches/*/project-a:refs/remotes/project-a/branches/*
	branches = branches/release_*:refs/remotes/project-a/branches/release_*
	branches = branches/re*se:refs/remotes/project-a/branches/*
	tags = tags/*/project-a:refs/remotes/project-a/tags/*

請記住,本地 ref(: 的右邊)的 * (星號) 通配符 必須 是最右邊的路徑元件;但是遠端通配符可以在任何地方,只要它是獨立的路徑元件(被 / 或 EOL 包圍)。這種配置不是由 init 自動建立的,應該使用文字編輯器或使用 git config 手動輸入。

另請注意,每個單字只允許一個星號。例如

branches = branches/re*se:refs/remotes/project-a/branches/*

將匹配分支 releaseresere123se,但是

branches = branches/re*s*e:refs/remotes/project-a/branches/*

將產生錯誤。

也可以使用大括號內的逗號分隔的名稱列表來提取分支或標籤的子集。例如

[svn-remote "huge-project"]
	url = http://server.org/svn
	fetch = trunk/src:refs/remotes/trunk
	branches = branches/{red,green}/src:refs/remotes/project-a/branches/*
	tags = tags/{1.0,2.0}/src:refs/remotes/project-a/tags/*

支援多個 fetch、branches 和 tags 鍵

[svn-remote "messy-repo"]
	url = http://server.org/svn
	fetch = trunk/project-a:refs/remotes/project-a/trunk
	fetch = branches/demos/june-project-a-demo:refs/remotes/project-a/demos/june-demo
	branches = branches/server/*:refs/remotes/project-a/branches/*
	branches = branches/demos/2011/*:refs/remotes/project-a/2011-demos/*
	tags = tags/server/*:refs/remotes/project-a/tags/*

在這種配置中建立分支需要使用 -d 或 --destination 旗標來消除使用哪個位置的歧義

$ git svn branch -d branches/server release-2-3-0

請注意,git-svn 會追蹤分支或標籤出現的最高修訂版本。如果在提取後變更分支或標籤的子集,則必須手動編輯 $GIT_DIR/svn/.metadata 以適當地移除(或重設)branches-maxRev 和/或 tags-maxRev。

檔案

$GIT_DIR/svn/**/.rev_map.*

Subversion 修訂版本號和 Git 提交名稱之間的對應關係。在未設定 noMetadata 選項的儲存庫中,可以從每個提交結尾的 git-svn-id: 行重建此對應關係(有關詳細資訊,請參閱上面的 svn.noMetadata 區段)。

git svn fetchgit svn rebase 會在遺失或不是最新時自動更新 rev_map。git svn reset 會自動倒回它。

錯誤

我們忽略除 svn:executable 之外的所有 SVN 屬性。任何未處理的屬性都會記錄到 $GIT_DIR/svn/<refname>/unhandled.log

Git 不會偵測到已重新命名和複製的目錄,因此在提交到 SVN 時不會追蹤它們。我沒有計劃新增對此的支援,因為要讓它在所有可能的邊緣情況下正常運作相當困難且耗時(Git 也沒有這樣做)。如果已重新命名和複製的檔案與 Git 偵測到的足夠相似,則完全支援提交這些檔案。

在 SVN 中,可以(儘管不建議)將變更提交到標籤(因為標籤只是一個目錄副本,因此技術上與分支相同)。在克隆 SVN 儲存庫時,git svn 無法知道未來是否會發生對標籤的提交。因此,它會採取保守的做法,並將所有 SVN 標籤作為分支匯入,並在標籤名稱前面加上 tags/

另請參閱

GIT

屬於 git[1] 套件的一部分

scroll-to-top