How does git-svn handle line endings?
Asked Answered
P

1

36

I'm pretty happy with how Git itself handles line endings, via core.autocrlf, core.eol + gitattributes (Tim's post is excellent).

I have a Windows Git repo that has autocrlf set to true. So, all text files are stored in the repo as LF and live in the working directory as CRLF. This repo was cloned from an SVN repo, which we still use to push from / pull to (the SVN repo is our central, blessed repo for triggering CI etc).

But I don't know how git-svn handles line endings during the push / pull operations.

Can anyone explain what git-svn does in this instance?

Pat answered 28/3, 2012 at 14:27 Comment(0)
E
16

I'm interested in this too. Supposing you have a repo that was created via git svn clone, I think you could break it down into three different questions:

  1. Does any git newline normalization/alteration happen at git svn fetch time, in moving commits from svn to the git repo?
  2. Does any git newline normalization/alteration happen at git commit time [i.e. during a normal local git commit to a repo with svn remotes]? How about merge/rebase time?
  3. Does any git newline normalization/alteration happen at git svn dcommit time, in pushing/replaying/whatever git commits against svn?

I'd love to hear what's theoretically supposed to be true for these questions, but for now I did a little experiment that seems to show that there is no newline normalization in case #1 at least:

rem We'll make a svn repo with CRLF newlines, clone it into git with
rem autocrlf enabled, and try to see if that results in LF-only newlines
rem getting stored in the git repo

cd c:\code

rem Step 1. Prepare SVN repo with CRLF type newlines.
rem The pre-1.4 flag is to prevent an error during git clone.

svnadmin create --pre-1.4-compatible svnrepo
svn checkout file:///C:/code/svnrepo svnworking
cd svnworking
echo "First line" > file.txt
echo "Second line" >> file.txt
echo "Third line" >> file.txt
rem NOTE: At this point file.txt has CRLF newlines
svn add file.txt
svn commit -m "Add file.txt"
rem NOTE: At this point file.txt still has CRLF newlines
cd ..

rem Step 2. Clone the svn repo into git and inspect work copy newline type
git svn clone file:///C:/code/svnrepo gitrepo
rem The following outputs true on my machine
git config --get core.autocrlf
cd gitrepo
rem The following also outputs true on my machine
git config --get core.autocrlf
git svn fetch
rem NOTE: At this point file.txt (git working dir copy) has CRLF newlines

rem Step 3. Disable autocrlf to inspect repo's inner newline type
rem Use the following and my editor to set core.autocrlf to false:
git config --edit --local
rem This now prints false:
git config --get core.autocrlf
git checkout .
rem NOTE: At this point file.txt (git working dir copy) still has CRLF newlines
del file.txt
git checkout .
rem NOTE: Even after explicitly deleting the old one and checking out again,
rem file.txt still has CRLF newlines

If git newline conversion had taken place during my git svn pull, in contrast, then I would expect file.txt to have LF-only newlines at the end of all this.

Here's a sanity check that step 3 above actually implements a valid test of whether the repo has LF-only newlines:

rem We'll a git repo with core.autocrlf on, then switch it off to
rem pull out a file

rem The following outputs true
git config --get core.autocrlf
git init gitcrtest
cd gitcrtest
rem The following still outputs true
git config --get core.autocrlf
echo "First line" > file.txt
echo "Second line" >> file.txt
echo "Third line" >> file.txt
git add file.txt
git commit -m "Add file.txt"
rem NOTE: At this point file.txt (git working dir copy) has CRLF newlines
rem Use the following to set core.autocrlf to false
git config --edit --local
git checkout .
rem NOTE: Now file.txt (git working dir copy) has LF-only newlines

In summary: Based on the above, it seems that when git-svn pulls from svn, the svn commits get added to the git commit graph without any crlf translation, even when autocrlf is enabled. That is, whatever type of newline your files have in your svn repo, they're also going to have in your git clone thereof. (But your git working copy may have different newline types.)

Note that this is pretty consistent with the discussion of end-of-line normalization in "git help attributes"; there normalization is presented as something that happens either with commands that pull stuff from the repo into your working directory (e.g. checkout or merge) or with commands that move things from your working directory into the index/repo (e.g. add or commit). "Git svn fetch" doesn't seem to do either of those things, so it makes sense that no end-of-line normalization would happen at that time. I'm fuzzier about what dcommit does, so I'm not sure whether to expect end-of-line normalization at that time.

Note there's an additional wrinkle if SVN's svn:eol-style property is set on your repo/machine. I think the SVN default is to not do end-of-line conversions on its end, but I'm not 100% sure.

Update: For a real-world svn->git migration perspective on newlines, see also Tim Abell's description thereof. CRLF newlines were not converted to LF-only newlines by git-svn, with non-ideal results if git's automatic end-of-line normalization was left on. Solutions were to normalize the line endings in git or to disable end-of-line-normalization.

Entero answered 29/3, 2012 at 4:29 Comment(1)
"I think the SVN default is to not do end-of-line conversions on its end" That's right, according to svnbook.red-bean.com/en/1.7/… "by default, Subversion doesn't pay any attention to the type of end-of-line (EOL) markers used in your files."Bookseller

© 2022 - 2024 — McMap. All rights reserved.