Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does git-svn handle line endings?

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?

like image 848
citizenmatt Avatar asked Mar 28 '12 14:03

citizenmatt


People also ask

How does git handle line endings?

text eol=crlf Git will always convert line endings to CRLF on checkout. You should use this for files that must keep CRLF endings, even on OSX or Linux. text eol=lf Git will always convert line endings to LF on checkout. You should use this for files that must keep LF endings, even on Windows.

Does GIT Preserve line endings?

Git cloning under Windows preserves line endings of relevant scripts and files regardless of a user's local Git configuration so it's possible to provision a VM with Vagrant, install and run LibreTime in place without issue.

Does GIT use LF or CRLF?

Git doesn't expect you to use unix-style LF under Windows. The warning "CRLF will be replaced by LF" says that you (having autocrlf = input ) will lose your windows-style CRLF after a commit-checkout cycle (it will be replaced by unix-style LF). Don't use input under Windows.

How does Git SVN work?

git svn is a git command that allows using git to interact with Subversion repositories. git svn is part of git, meaning that is NOT a plugin but actually bundled with your git installation. SourceTree also happens to support this command so you can use it with your usual workflow.


1 Answers

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.

like image 121
Chris Avatar answered Oct 07 '22 21:10

Chris