diff --git a/src/dep.h b/src/dep.h
index 5b60521f..abdfaf45 100644
--- a/src/dep.h
+++ b/src/dep.h
@@ -42,7 +42,6 @@ struct nameseq
    explicit is set when implicit rule search is performed and the prerequisite
    does not contain %. When explicit is set the file is not intermediate.  */
 
-
 #define DEP(_t)                                 \
     NAMESEQ (_t);                               \
     struct file *file;                          \
@@ -132,6 +131,7 @@ SI void free_goal_chain (struct goaldep *g) { free_dep_chain((struct dep *)g); }
 # define free_goal_chain(_g) free_ns_chain ((struct nameseq *)(_g))
 #endif
 
+struct dep *copy_dep (const struct dep *d);
 struct dep *copy_dep_chain (const struct dep *d);
 
 struct goaldep *read_all_makefiles (const char **makefiles);
diff --git a/src/misc.c b/src/misc.c
index a53301df..1914aa22 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -528,23 +528,38 @@ readbuf (int fd, void *buffer, size_t len)
 }
 
 
+/* Copy a 'struct dep'.  For 2nd expansion deps, dup the name.  */
+
+struct dep *
+copy_dep (const struct dep *d)
+{
+  struct dep *new = NULL;
+
+  if (d)
+    {
+      new = xmalloc (sizeof (struct dep));
+      memcpy (new, d, sizeof (struct dep));
+
+      if (new->need_2nd_expansion)
+        new->name = xstrdup (new->name);
+      new->next = 0;
+    }
+
+  return new;
+}
+
 /* Copy a chain of 'struct dep'.  For 2nd expansion deps, dup the name.  */
 
 struct dep *
 copy_dep_chain (const struct dep *d)
 {
-  struct dep *firstnew = 0;
-  struct dep *lastnew = 0;
+  struct dep *firstnew = NULL;
+  struct dep *lastnew = NULL;
 
   while (d != 0)
     {
-      struct dep *c = xmalloc (sizeof (struct dep));
-      memcpy (c, d, sizeof (struct dep));
+      struct dep *c = copy_dep (d);
 
-      if (c->need_2nd_expansion)
-        c->name = xstrdup (c->name);
-
-      c->next = 0;
       if (firstnew == 0)
         firstnew = lastnew = c;
       else
@@ -562,7 +577,7 @@ copy_dep_chain (const struct dep *d)
 void
 free_ns_chain (struct nameseq *ns)
 {
-  while (ns != 0)
+  while (ns != NULL)
     {
       struct nameseq *t = ns;
       ns = ns->next;
diff --git a/src/read.c b/src/read.c
index 0fb783a2..8a487a94 100644
--- a/src/read.c
+++ b/src/read.c
@@ -2110,7 +2110,6 @@ record_files (struct nameseq *filenames, int are_also_makes,
       return;
     }
 
-
   /* Walk through each target and create it in the database.
      We already set up the first target, above.  */
   while (1)
@@ -2283,15 +2282,14 @@ record_files (struct nameseq *filenames, int are_also_makes,
     }
 
   /* If there are also-makes, then populate a copy of the also-make list into
-     each one. For the last file, we take our original also_make list instead
-     wastefully copying it one more time and freeing it.  */
+     each one.  Omit the file from its also-make list.  */
   {
     struct dep *i;
 
     for (i = also_make; i != NULL; i = i->next)
       {
         struct file *f = i->file;
-        struct dep *cpy = i->next ? copy_dep_chain (also_make) : also_make;
+        struct dep *dp;
 
         if (f->also_make)
           {
@@ -2299,11 +2297,20 @@ record_files (struct nameseq *filenames, int are_also_makes,
                 _("warning: overriding group membership for target '%s'"),
                 f->name);
             free_dep_chain (f->also_make);
+            f->also_make = NULL;
           }
 
-        f->also_make = cpy;
+        for (dp = also_make; dp != NULL; dp = dp->next)
+          if (dp->file != f)
+            {
+              struct dep *cpy = copy_dep (dp);
+              cpy->next = f->also_make;
+              f->also_make = cpy;
+            }
       }
-    }
+
+    free_dep_chain (also_make);
+  }
 }
 
 /* Search STRING for an unquoted STOPMAP.