threads / discuss / 18407

git am from scratch

Subject: git am from scratch

## tl;dr

8 messages between Mar 19, 2009 and Mar 20, 2009.

replies: 7people: 4as markdown or json

Andreas Gruenbacher· Mar 19, 2009, 15:09 UTC · lore
Hello,

lates git (e986ceb0): there is a bug in git am when trying to recreate the entire history of a repository:

	$ git format-patch --stdout rcs-history \
		| ( rm -rf fOo && mkdir fOo && cd fOo && git init && git am )
	Initialized empty Git repository in /home/agruen/git/patch/foo/.git/
	fatal: HEAD: not a valid SHA1
	fatal: bad revision 'HEAD'

When the first commit is added by hand instead, git am will import the rest of the mbox without problems. This is annoying because it's at least not immediately obvious how to recreate the initial commit with all the metadata.

Is this easily fixed?

Thanks, Andreas

Jeff King· Mar 19, 2009, 20:18 UTC · re: Andreas Gruenbacher · lore

Re: git am from scratch

On Thu, Mar 19, 2009 at 04:09:24PM +0100, Andreas Gruenbacher wrote:
> lates git (e986ceb0): there is a bug in git am when trying to recreate the 
> entire history of a repository:
I don't think this has ever worked in any version of git.

It might be nice to have, since it does come up once in a while, so I suspect patches would be welcome.

But...
Show 6 quoted lines
> When the first commit is added by hand instead, git am will import the
> rest of the mbox without problems. This is annoying because it's at
> least not immediately obvious how to recreate the initial commit with
> all the metadata.
> 
> Is this easily fixed?
There are many other ways to do this. Have you tried:
  - simply pulling the old repo into the new one?
  - if they are not connected in real-time, creating a bundle from the
    first and pulling it into the latter?
  - if you want to tweak the commit data during the process, have you
    tried using fast-export/fast-import rather than format-patch/am?
-Peff
Andreas Gruenbacher· Mar 19, 2009, 20:42 UTC · re: Jeff King · lore

Re: git am from scratch

On Thursday, 19 March 2009 21:18:17 Jeff King wrote:
> I don't think this has ever worked in any version of git.

I did find a way to help myself in the end. Still it was still a major, unnecessary annoyance.

I ran into this problem when trying to reconstruct a project's history (after going RCS -> CVS -> git many things were still wrong like unrelated RCS files which ended up in the history, RCS files being moved to the Attic in the original tree to indicate deletes [which means they will happily live on from a CVS point of view], etc.).

The easiest way I could find how to get rid of all the mess without going totally insane was to git-format-patch the repository, fix up the major things in the mbox, and then recreate the history.

In the end I ended up preparing the initial commit by hand followed by "commit -c HASH" to preserve the metadata. (The cvsimport branch had a different commit at its tip, so I couldn't use commit --amend on that.) After that, I git-am'ed the rest of the mbox onto that reconstructed commit. This could have been significantly easier.

> There are many other ways to do this.
That's really not the point. Thanks though.
Andreas
Jeff King· Mar 19, 2009, 21:02 UTC · re: Andreas Gruenbacher · lore

Re: git am from scratch

On Thu, Mar 19, 2009 at 09:42:49PM +0100, Andreas Gruenbacher wrote:
> > I don't think this has ever worked in any version of git.
> I did find a way to help myself in the end. Still it was still a major, 
> unnecessary annoyance.

Sure, and that is why I suggested a patch for git-am might be welcome; it's not the right tool for the job, but it seems to be one that people naturally think of.

Show 5 quoted lines
> I ran into this problem when trying to reconstruct a project's history (after 
> going RCS -> CVS -> git many things were still wrong like unrelated RCS files 
> which ended up in the history, RCS files being moved to the Attic in the 
> original tree to indicate deletes [which means they will happily live on from 
> a CVS point of view], etc.).
Yikes. Out of curiosity, what did you use to do the CVS import?

Anyway, here is a not-very-well-tested patch to get "git am" to apply on top of an empty repository (i.e., it worked on my utterly simplistic test case and I didn't think too hard about what else might have been broken). Maybe it will give a good start to somebody who wants to work on this.

---
diff --git a/git-am.sh b/git-am.sh
index d339075..bcc600d 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -290,17 +290,23 @@ else
 		: >"$dotest/rebasing"
 	else
 		: >"$dotest/applying"
-		git update-ref ORIG_HEAD HEAD
+		if git rev-parse --quiet --verify HEAD; then
+			git update-ref ORIG_HEAD HEAD
+		else
+			rm -f "$GIT_DIR/ORIG_HEAD"
+		fi
 	fi
 fi
 
 case "$resolved" in
 '')
-	files=$(git diff-index --cached --name-only HEAD --) || exit
-	if test "$files"
-	then
-		: >"$dotest/dirtyindex"
-		die "Dirty index: cannot apply patches (dirty: $files)"
+	if git rev-parse --quiet --verify HEAD; then
+		files=$(git diff-index --cached --name-only HEAD --) || exit
+		if test "$files"
+		then
+			: >"$dotest/dirtyindex"
+			die "Dirty index: cannot apply patches (dirty: $files)"
+		fi
 	fi
 esac
 
@@ -541,7 +547,7 @@ do
 	fi
 
 	tree=$(git write-tree) &&
-	parent=$(git rev-parse --verify HEAD) &&
+	parent=$(git rev-parse --quiet --verify HEAD)
 	commit=$(
 		if test -n "$ignore_date"
 		then
@@ -552,7 +558,7 @@ do
 			GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
 			export GIT_COMMITTER_DATE
 		fi &&
-		git commit-tree $tree -p $parent <"$dotest/final-commit"
+		git commit-tree $tree ${parent:+-p $parent} <"$dotest/final-commit"
 	) &&
 	git update-ref -m "$GIT_REFLOG_ACTION: $FIRSTLINE" HEAD $commit $parent ||
 	stop_here $this
Junio C Hamano· Mar 19, 2009, 21:57 UTC · re: Jeff King · lore

Re: git am from scratch

Jeff King <peff@peff.net> writes:
Show 5 quoted lines
> Anyway, here is a not-very-well-tested patch to get "git am" to apply on
> top of an empty repository (i.e., it worked on my utterly simplistic
> test case and I didn't think too hard about what else might have been
> broken). Maybe it will give a good start to somebody who wants to work
> on this.

The patch gets the ball rolling in a right direction, I think. In addition, you need to audit --abort and --skip codepaths carefully, though.

Show 52 quoted lines
> diff --git a/git-am.sh b/git-am.sh
> index d339075..bcc600d 100755
> --- a/git-am.sh
> +++ b/git-am.sh
> @@ -290,17 +290,23 @@ else
>  		: >"$dotest/rebasing"
>  	else
>  		: >"$dotest/applying"
> -		git update-ref ORIG_HEAD HEAD
> +		if git rev-parse --quiet --verify HEAD; then
> +			git update-ref ORIG_HEAD HEAD
> +		else
> +			rm -f "$GIT_DIR/ORIG_HEAD"
> +		fi
>  	fi
>  fi
>  
>  case "$resolved" in
>  '')
> -	files=$(git diff-index --cached --name-only HEAD --) || exit
> -	if test "$files"
> -	then
> -		: >"$dotest/dirtyindex"
> -		die "Dirty index: cannot apply patches (dirty: $files)"
> +	if git rev-parse --quiet --verify HEAD; then
> +		files=$(git diff-index --cached --name-only HEAD --) || exit
> +		if test "$files"
> +		then
> +			: >"$dotest/dirtyindex"
> +			die "Dirty index: cannot apply patches (dirty: $files)"
> +		fi
>  	fi
>  esac
>  
> @@ -541,7 +547,7 @@ do
>  	fi
>  
>  	tree=$(git write-tree) &&
> -	parent=$(git rev-parse --verify HEAD) &&
> +	parent=$(git rev-parse --quiet --verify HEAD)
>  	commit=$(
>  		if test -n "$ignore_date"
>  		then
> @@ -552,7 +558,7 @@ do
>  			GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
>  			export GIT_COMMITTER_DATE
>  		fi &&
> -		git commit-tree $tree -p $parent <"$dotest/final-commit"
> +		git commit-tree $tree ${parent:+-p $parent} <"$dotest/final-commit"
>  	) &&
>  	git update-ref -m "$GIT_REFLOG_ACTION: $FIRSTLINE" HEAD $commit $parent ||
>  	stop_here $this
Jeff King· Mar 20, 2009, 04:39 UTC · re: Andreas Gruenbacher · lore

Re: git am from scratch

On Fri, Mar 20, 2009 at 02:06:24AM +0100, Andreas Gruenbacher wrote:
> On Thursday, 19 March 2009 22:02:14 Jeff King wrote:
> > Yikes. Out of curiosity, what did you use to do the CVS import?
> 
> git-cvsimport

Ah. It sounds like you have already resolved all of your issues by munging the resulting history, but you may have better success on a complex history with a different tool like cvs2git or parsecvs (even if you have fixed it, you may want to investigate them to double-check your result).

-Peff

← back to recent threads