diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java
index 0c8210f646b564eb28b67b1bfb7bb8ea2d8eecf7..4a205fffbe120331be7d28ece2a919e69c675890 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java
@@ -623,7 +623,7 @@ private void searchForReuse(
 			selectDeltaReuseForObject(otp, reuseLoaders);
 		}
 		// delta reuse is preferred over object reuse
-		if (reuseObjects && !otp.hasReuseLoader()) {
+		if (reuseObjects && !otp.isCopyable()) {
 			selectObjectReuseForObject(otp, reuseLoaders);
 		}
 	}
@@ -649,7 +649,7 @@ && isBetterDeltaReuseLoader(bestLoader, loader)) {
 		}
 
 		if (bestLoader != null) {
-			otp.setReuseLoader(bestLoader);
+			otp.setCopyFromPack(bestLoader);
 			otp.setDeltaBase(bestBase);
 		}
 	}
@@ -670,7 +670,7 @@ private void selectObjectReuseForObject(final ObjectToPack otp,
 			final Collection<PackedObjectLoader> loaders) {
 		for (final PackedObjectLoader loader : loaders) {
 			if (loader instanceof WholePackedObjectLoader) {
-				otp.setReuseLoader(loader);
+				otp.setCopyFromPack(loader);
 				return;
 			}
 		}
@@ -703,7 +703,7 @@ private void writeObject(final ObjectToPack otp) throws IOException {
 			if (deltaBase != null && !deltaBase.isWritten()) {
 				if (deltaBase.wantWrite()) {
 					otp.clearDeltaBase(); // cycle detected
-					otp.disposeLoader();
+					otp.clearSourcePack();
 				} else {
 					writeObject(deltaBase);
 				}
@@ -737,13 +737,9 @@ private void writeObject(final ObjectToPack otp) throws IOException {
 	}
 
 	private PackedObjectLoader open(final ObjectToPack otp) throws IOException {
-		for (;;) {
-			PackedObjectLoader reuse = otp.useLoader();
-			if (reuse == null) {
-				return null;
-			}
-
+		while (otp.isCopyable()) {
 			try {
+				PackedObjectLoader reuse = otp.getCopyLoader(windowCursor);
 				reuse.beginCopyRawData();
 				return reuse;
 			} catch (IOException err) {
@@ -751,10 +747,12 @@ private PackedObjectLoader open(final ObjectToPack otp) throws IOException {
 				// it has been overwritten with a different layout.
 				//
 				otp.clearDeltaBase();
+				otp.clearSourcePack();
 				searchForReuse(new ArrayList<PackedObjectLoader>(), otp);
 				continue;
 			}
 		}
+		return null;
 	}
 
 	private void writeWholeObjectDeflate(final ObjectToPack otp)
@@ -904,9 +902,14 @@ public void addObject(final RevObject object)
 	 *
 	 */
 	static class ObjectToPack extends PackedObjectInfo {
+		/** Other object being packed that this will delta against. */
 		private ObjectId deltaBase;
 
-		private PackedObjectLoader reuseLoader;
+		/** Pack to reuse compressed data from, otherwise null. */
+		private PackFile copyFromPack;
+
+		/** Offset of the object's header in {@link #copyFromPack}. */
+		private long copyOffset;
 
 		/**
 		 * Bit field, from bit 0 to bit 31:
@@ -989,22 +992,21 @@ boolean isWritten() {
 			return getOffset() != 0;
 		}
 
-		PackedObjectLoader useLoader() {
-			final PackedObjectLoader r = reuseLoader;
-			reuseLoader = null;
-			return r;
+		boolean isCopyable() {
+			return copyFromPack != null;
 		}
 
-		boolean hasReuseLoader() {
-			return reuseLoader != null;
+		PackedObjectLoader getCopyLoader(WindowCursor curs) throws IOException {
+			return copyFromPack.resolveBase(curs, copyOffset);
 		}
 
-		void setReuseLoader(PackedObjectLoader reuseLoader) {
-			this.reuseLoader = reuseLoader;
+		void setCopyFromPack(PackedObjectLoader loader) {
+			this.copyFromPack = loader.pack;
+			this.copyOffset = loader.objectOffset;
 		}
 
-		void disposeLoader() {
-			this.reuseLoader = null;
+		void clearSourcePack() {
+			copyFromPack = null;
 		}
 
 		int getType() {