diff --git a/cmd/helm/repo_index.go b/cmd/helm/repo_index.go
index 636d900900470a4efe9aff62e201fcc7a865655a..f88127c918ae8512758c944a674451d244e1f900 100644
--- a/cmd/helm/repo_index.go
+++ b/cmd/helm/repo_index.go
@@ -25,10 +25,22 @@ import (
 	"k8s.io/helm/pkg/repo"
 )
 
+const repoIndexDesc = `
+Read the current directory and generate an index file based on the charts found.
+
+This tool is used for creating an 'index.yaml' file for a chart repository. To
+set an absolute URL to the charts, use '--url' flag.
+
+To merge the generated index with an existing index file, use the '--merge'
+flag. In this case, the charts found in the current directory will be merged
+into the existing index, with local charts taking priority over existing charts.
+`
+
 type repoIndexCmd struct {
-	dir string
-	url string
-	out io.Writer
+	dir   string
+	url   string
+	out   io.Writer
+	merge string
 }
 
 func newRepoIndexCmd(out io.Writer) *cobra.Command {
@@ -39,6 +51,7 @@ func newRepoIndexCmd(out io.Writer) *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "index [flags] [DIR]",
 		Short: "generate an index file given a directory containing packaged charts",
+		Long:  repoIndexDesc,
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if err := checkArgsLength(len(args), "path to a directory"); err != nil {
 				return err
@@ -52,6 +65,7 @@ func newRepoIndexCmd(out io.Writer) *cobra.Command {
 
 	f := cmd.Flags()
 	f.StringVar(&index.url, "url", "", "url of chart repository")
+	f.StringVar(&index.merge, "merge", "", "merge the generated index into the given index")
 
 	return cmd
 }
@@ -62,14 +76,22 @@ func (i *repoIndexCmd) run() error {
 		return err
 	}
 
-	return index(path, i.url)
+	return index(path, i.url, i.merge)
 }
 
-func index(dir, url string) error {
+func index(dir, url, mergeTo string) error {
 	chartRepo, err := repo.LoadChartRepository(dir, url)
 	if err != nil {
 		return err
 	}
 
+	if mergeTo != "" {
+		old, err := repo.LoadIndexFile(mergeTo)
+		if err != nil {
+			return err
+		}
+		return chartRepo.MergeIndex(old)
+	}
+
 	return chartRepo.Index()
 }
diff --git a/cmd/helm/repo_index_test.go b/cmd/helm/repo_index_test.go
index d207a8b5ee114f34a0cecec2323d21cab948a285..ee00d546dab689054219cc7810887091a339011b 100644
--- a/cmd/helm/repo_index_test.go
+++ b/cmd/helm/repo_index_test.go
@@ -33,7 +33,9 @@ func TestRepoIndexCmd(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer os.RemoveAll(dir)
-	if err := os.Link("testdata/testcharts/compressedchart-0.1.0.tgz", filepath.Join(dir, "compressedchart-0.1.0.tgz")); err != nil {
+
+	comp := filepath.Join(dir, "compressedchart-0.1.0.tgz")
+	if err := os.Link("testdata/testcharts/compressedchart-0.1.0.tgz", comp); err != nil {
 		t.Fatal(err)
 	}
 
@@ -41,16 +43,42 @@ func TestRepoIndexCmd(t *testing.T) {
 	c := newRepoIndexCmd(buf)
 
 	if err := c.RunE(c, []string{dir}); err != nil {
-		t.Errorf("%q", err)
+		t.Error(err)
 	}
 
-	index, err := repo.LoadIndexFile(filepath.Join(dir, "index.yaml"))
+	destIndex := filepath.Join(dir, "index.yaml")
+
+	index, err := repo.LoadIndexFile(destIndex)
 	if err != nil {
 		t.Fatal(err)
 	}
 
 	if len(index.Entries) != 1 {
-		t.Errorf("expected 1 entry, got %v: %#v", len(index.Entries), index.Entries)
+		t.Errorf("expected 1 entry, got %d: %#v", len(index.Entries), index.Entries)
+	}
+
+	// Test with `--merge`
+
+	// Remove first chart.
+	if err := os.Remove(comp); err != nil {
+		t.Fatal(err)
+	}
+	// Add another chart.
+	if err := os.Link("testdata/testcharts/reqtest-0.1.0.tgz", filepath.Join(dir, "reqtest-0.1.0.tgz")); err != nil {
+		t.Fatal(err)
 	}
 
+	c.ParseFlags([]string{"--merge", destIndex})
+	if err := c.RunE(c, []string{dir}); err != nil {
+		t.Error(err)
+	}
+
+	index, err = repo.LoadIndexFile(destIndex)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(index.Entries) != 2 {
+		t.Errorf("expected 2 entry, got %d: %#v", len(index.Entries), index.Entries)
+	}
 }
diff --git a/pkg/repo/index_test.go b/pkg/repo/index_test.go
index 080023f24914faedb9637beb8f950ea118c34e03..6f096103b953d49b7c8410bc74befae20055a385 100644
--- a/pkg/repo/index_test.go
+++ b/pkg/repo/index_test.go
@@ -82,6 +82,67 @@ func TestLoadIndexFile(t *testing.T) {
 	verifyLocalIndex(t, i)
 }
 
+func TestMergeIndex(t *testing.T) {
+	dirName, err := ioutil.TempDir("", "tmp")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(dirName)
+
+	ind := NewIndexFile()
+	ind.Add(&chart.Metadata{
+		Name:    "dreadnought",
+		Version: "0.1.0",
+	}, "dreadnought-0.1.0.tgz", "http://example.com", "aaaa")
+
+	cr := &ChartRepository{
+		IndexFile: ind,
+		RootPath:  dirName,
+	}
+
+	if err := cr.saveIndexFile(); err != nil {
+		t.Fatal(err)
+	}
+
+	ind2 := NewIndexFile()
+	ind2.Add(&chart.Metadata{
+		Name:    "dreadnought",
+		Version: "0.2.0",
+	}, "dreadnought-0.2.0.tgz", "http://example.com", "aaaabbbb")
+	ind2.Add(&chart.Metadata{
+		Name:    "doughnut",
+		Version: "0.2.0",
+	}, "doughnut-0.2.0.tgz", "http://example.com", "ccccbbbb")
+	cr.IndexFile = ind2
+
+	ind3, err := LoadIndexFile(filepath.Join(dirName, "index.yaml"))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := cr.MergeIndex(ind3); err != nil {
+		t.Fatal(err)
+	}
+
+	ind4, err := LoadIndexFile(filepath.Join(dirName, "index.yaml"))
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if len(ind4.Entries) != 2 {
+		t.Errorf("Expected 2 entries, got %d", len(ind4.Entries))
+		vs := ind4.Entries["dreadnaught"]
+		if len(vs) != 2 {
+			t.Errorf("Expected 2 versions, got %d", len(vs))
+		}
+		v := vs[0]
+		if v.Version != "0.2.0" {
+			t.Errorf("Expected %q version to be 0.2.0, got %s", v.Name, v.Version)
+		}
+	}
+
+}
+
 func TestDownloadIndexFile(t *testing.T) {
 	fileBytes, err := ioutil.ReadFile("testdata/local-index.yaml")
 	if err != nil {
diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go
index baa66a7d9946801f6c87367772a145ab529169da..e1d9d4712457b0f5e969a6d3539da987a67bb9b6 100644
--- a/pkg/repo/repo.go
+++ b/pkg/repo/repo.go
@@ -191,6 +191,35 @@ func (r *ChartRepository) saveIndexFile() error {
 
 // Index generates an index for the chart repository and writes an index.yaml file.
 func (r *ChartRepository) Index() error {
+	err := r.generateIndex()
+	if err != nil {
+		return err
+	}
+	return r.saveIndexFile()
+}
+
+// MergeIndex merges the given index file into this index, and then writes the result.
+//
+// This provides a parallel function to the Index() method, but with the additional merge step.
+func (r *ChartRepository) MergeIndex(f *IndexFile) error {
+	err := r.generateIndex()
+	if err != nil {
+		return err
+	}
+
+	for _, cvs := range f.Entries {
+		for _, cv := range cvs {
+			if !r.IndexFile.Has(cv.Name, cv.Version) {
+				e := r.IndexFile.Entries[cv.Name]
+				r.IndexFile.Entries[cv.Name] = append(e, cv)
+			}
+		}
+	}
+
+	return r.saveIndexFile()
+}
+
+func (r *ChartRepository) generateIndex() error {
 	if r.IndexFile == nil {
 		r.IndexFile = NewIndexFile()
 	}
@@ -212,5 +241,5 @@ func (r *ChartRepository) Index() error {
 		// TODO: If a chart exists, but has a different Digest, should we error?
 	}
 	r.IndexFile.SortEntries()
-	return r.saveIndexFile()
+	return nil
 }