packp: fixed encoding when HEAD is not a valid ref
diff --git a/plumbing/protocol/packp/advrefs_encode.go b/plumbing/protocol/packp/advrefs_encode.go
index e981120..cb93d46 100644
--- a/plumbing/protocol/packp/advrefs_encode.go
+++ b/plumbing/protocol/packp/advrefs_encode.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"fmt"
 	"io"
 	"sort"
 
@@ -21,9 +22,13 @@
 }
 
 type advRefsEncoder struct {
-	data *AdvRefs         // data to encode
-	pe   *pktline.Encoder // where to write the encoded data
-	err  error            // sticky error
+	data         *AdvRefs         // data to encode
+	pe           *pktline.Encoder // where to write the encoded data
+	firstRefName string           // reference name to encode in the first pkt-line (HEAD if present)
+	firstRefHash plumbing.Hash    // hash referenced to encode in the first pkt-line (HEAD if present)
+	sortedRefs   []string         // hash references to encode ordered by increasing order
+	err          error            // sticky error
+
 }
 
 func newAdvRefsEncoder(w io.Writer) *advRefsEncoder {
@@ -34,6 +39,8 @@
 
 func (e *advRefsEncoder) Encode(v *AdvRefs) error {
 	e.data = v
+	e.sortRefs()
+	e.setFirstRef()
 
 	for state := encodePrefix; state != nil; {
 		state = state(e)
@@ -42,6 +49,32 @@
 	return e.err
 }
 
+func (e *advRefsEncoder) sortRefs() {
+	if len(e.data.References) > 0 {
+		refs := make([]string, 0, len(e.data.References))
+		for refName := range e.data.References {
+			refs = append(refs, refName)
+		}
+
+		sort.Strings(refs)
+		e.sortedRefs = refs
+	}
+}
+
+func (e *advRefsEncoder) setFirstRef() {
+	if e.data.Head != nil {
+		e.firstRefName = head
+		e.firstRefHash = *e.data.Head
+		return
+	}
+
+	if len(e.sortedRefs) > 0 {
+		refName := e.sortedRefs[0]
+		e.firstRefName = refName
+		e.firstRefHash = e.data.References[refName]
+	}
+}
+
 type encoderStateFn func(*advRefsEncoder) encoderStateFn
 
 func encodePrefix(e *advRefsEncoder) encoderStateFn {
@@ -61,35 +94,29 @@
 }
 
 // Adds the first pkt-line payload: head hash, head ref and capabilities.
-// Also handle the special case when no HEAD ref is found.
+// If HEAD ref is not found, the first reference ordered in increasing order will be used.
+// If there aren't HEAD neither refs, the first line will be "PKT-LINE(zero-id SP "capabilities^{}" NUL capability-list)".
+// See: https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt
+// See: https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt
 func encodeFirstLine(e *advRefsEncoder) encoderStateFn {
-	head := formatHead(e.data.Head)
-	separator := formatSeparator(e.data.Head)
+	const formatFirstLine = "%s %s\x00%s\n"
+	var firstLine string
 	capabilities := formatCaps(e.data.Capabilities)
 
-	if e.err = e.pe.Encodef("%s %s\x00%s\n", head, separator, capabilities); e.err != nil {
+	if e.firstRefName == "" {
+		firstLine = fmt.Sprintf(formatFirstLine, plumbing.ZeroHash.String(), "capabilities^{}", capabilities)
+	} else {
+		firstLine = fmt.Sprintf(formatFirstLine, e.firstRefHash.String(), e.firstRefName, capabilities)
+
+	}
+
+	if e.err = e.pe.EncodeString(firstLine); e.err != nil {
 		return nil
 	}
 
 	return encodeRefs
 }
 
-func formatHead(h *plumbing.Hash) string {
-	if h == nil {
-		return plumbing.ZeroHash.String()
-	}
-
-	return h.String()
-}
-
-func formatSeparator(h *plumbing.Hash) string {
-	if h == nil {
-		return noHead
-	}
-
-	return head
-}
-
 func formatCaps(c *capability.List) string {
 	if c == nil {
 		return ""
@@ -101,8 +128,11 @@
 // Adds the (sorted) refs: hash SP refname EOL
 // and their peeled refs if any.
 func encodeRefs(e *advRefsEncoder) encoderStateFn {
-	refs := sortRefs(e.data.References)
-	for _, r := range refs {
+	for _, r := range e.sortedRefs {
+		if r == e.firstRefName {
+			continue
+		}
+
 		hash, _ := e.data.References[r]
 		if e.err = e.pe.Encodef("%s %s\n", hash.String(), r); e.err != nil {
 			return nil
@@ -118,16 +148,6 @@
 	return encodeShallow
 }
 
-func sortRefs(m map[string]plumbing.Hash) []string {
-	ret := make([]string, 0, len(m))
-	for k := range m {
-		ret = append(ret, k)
-	}
-	sort.Strings(ret)
-
-	return ret
-}
-
 // Adds the (sorted) shallows: "shallow" SP hash EOL
 func encodeShallow(e *advRefsEncoder) encoderStateFn {
 	sorted := sortShallows(e.data.Shallows)
diff --git a/plumbing/protocol/packp/advrefs_encode_test.go b/plumbing/protocol/packp/advrefs_encode_test.go
index f901440..3ae84a7 100644
--- a/plumbing/protocol/packp/advrefs_encode_test.go
+++ b/plumbing/protocol/packp/advrefs_encode_test.go
@@ -99,8 +99,7 @@
 	}
 
 	expected := pktlines(c,
-		"0000000000000000000000000000000000000000 capabilities^{}\x00\n",
-		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\n",
+		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\x00\n",
 		"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
 		"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
 		"2222222222222222222222222222222222222222 refs/tags/v2.6.13-tree\n",
@@ -129,8 +128,7 @@
 	}
 
 	expected := pktlines(c,
-		"0000000000000000000000000000000000000000 capabilities^{}\x00\n",
-		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\n",
+		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\x00\n",
 		"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
 		"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
 		"5555555555555555555555555555555555555555 refs/tags/v2.6.12-tree^{}\n",