void CBrowseRefsDlg::Refresh(CString selectRef)
{
	remotes.clear();
	if (g_Git.GetRemoteList(remotes))
		MessageBox(CGit::GetLibGit2LastErr(_T("Could not get a list of remotes.")), _T("TortoiseGit"), MB_ICONERROR);

	if(!selectRef.IsEmpty())
	{
		if(selectRef == "HEAD")
		{
			if (g_Git.GetCurrentBranchFromFile(g_Git.m_CurrentDir, selectRef))
				selectRef.Empty();
			else
				selectRef = L"refs/heads/" + selectRef;
		}
	}
	else
	{
		selectRef = GetSelectedRef(false, true);
	}

	m_RefTreeCtrl.DeleteAllItems();
	m_ListRefLeafs.DeleteAllItems();
	m_TreeRoot.m_ShadowTree.clear();
	m_TreeRoot.m_csRefName = "refs";
	m_TreeRoot.m_hTree=m_RefTreeCtrl.InsertItem(L"refs",NULL,NULL);
	m_RefTreeCtrl.SetItemData(m_TreeRoot.m_hTree,(DWORD_PTR)&m_TreeRoot);

	CString err;
	MAP_REF_GITREVREFBROWSER refMap;
	if (GitRevRefBrowser::GetGitRevRefMap(refMap, err, [&](const CString& refName)
	{
		//Use ref based on m_pickRef_Kind
		if (wcsncmp(refName, L"refs/heads/", 11) == 0 && !(m_pickRef_Kind & gPickRef_Head))
			return false; //Skip
		if (wcsncmp(refName, L"refs/tags/", 10) == 0 && !(m_pickRef_Kind & gPickRef_Tag))
			return false; //Skip
		if (wcsncmp(refName, L"refs/remotes/", 13) == 0 && !(m_pickRef_Kind & gPickRef_Remote))
			return false; //Skip
		if (m_pickRef_Kind == gPickRef_Remote && wcsncmp(refName, L"refs/remotes/", 13) != 0) // do not show refs/stash if only remote branches are requested
			return false;
		return true;
	}))
	{
		MessageBox(_T("Get refs failed:") + err, _T("TortoiseGit"), MB_OK | MB_ICONERROR);
	}

	//Populate ref tree
	for (auto iterRefMap = refMap.cbegin(); iterRefMap != refMap.cend(); ++iterRefMap)
	{
		CShadowTree& treeLeaf = GetTreeNode(iterRefMap->first, nullptr, true);
		GitRevRefBrowser ref = iterRefMap->second;

		treeLeaf.m_csRefHash = ref.m_CommitHash.ToString();
		treeLeaf.m_csUpstream = ref.m_UpstreamRef;
		CGit::GetShortName(treeLeaf.m_csUpstream, treeLeaf.m_csUpstream, L"refs/remotes/");
		treeLeaf.m_csSubject = ref.GetSubject();
		treeLeaf.m_csAuthor = ref.GetAuthorName();
		treeLeaf.m_csDate = ref.GetAuthorDate();
		treeLeaf.m_csDescription = ref.m_Description;
	}

	// always expand the tree first
	m_RefTreeCtrl.Expand(m_TreeRoot.m_hTree, TVE_EXPAND);

	// try exact match first
	if (!selectRef.IsEmpty() && !SelectRef(selectRef, true))
		SelectRef(selectRef, false);
}
static void GetGitRevRefMap()
{
	g_Git.SetConfigValue(L"branch.master.description", L"test");
	g_Git.SetConfigValue(L"branch.subdir/branch.description", L"multi\nline");

	MAP_REF_GITREVREFBROWSER refMap;
	CString err;
	EXPECT_EQ(0, GitRevRefBrowser::GetGitRevRefMap(refMap, 0, err));
	EXPECT_STREQ(L"", err);
	EXPECT_EQ(12U, refMap.size());

	GitRevRefBrowser rev = refMap[L"refs/heads/master"];
	EXPECT_STREQ(L"7c3cbfe13a929d2291a574dca45e4fd2d2ac1aa6", rev.m_CommitHash.ToString());
	EXPECT_STREQ(L"Sven Strickroth", rev.GetAuthorName());
	EXPECT_STREQ(L"2015-03-07 18:03:58", rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(L"Changed ASCII file", rev.GetSubject());
	EXPECT_STREQ(L"refs/remotes/origin/master", rev.m_UpstreamRef);
	EXPECT_STREQ(L"test", rev.m_Description);

	rev = refMap[L"refs/heads/signed-commit"];
	EXPECT_STREQ(L"4c5c93d2a0b368bc4570d5ec02ab03b9c4334d44", rev.m_CommitHash.ToString());
	EXPECT_STREQ(L"Sven Strickroth", rev.GetAuthorName());
	EXPECT_STREQ(L"2015-03-16 12:52:29", rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(L"Several actions", rev.GetSubject());
	EXPECT_STREQ(L"", rev.m_UpstreamRef);
	EXPECT_STREQ(L"", rev.m_Description);

	rev = refMap[L"refs/tags/also-signed"];
	EXPECT_STREQ(L"e89cb722e0f9b2eb763bb059dc099ee6c502a6d8", rev.m_CommitHash.ToString());
	EXPECT_STREQ(L"Sven Strickroth", rev.GetAuthorName());
	EXPECT_STREQ(L"2015-03-04 17:45:40", rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S"));
	EXPECT_STREQ(L"Also signed", rev.GetSubject());
	EXPECT_STREQ(L"", rev.m_UpstreamRef);
	EXPECT_STREQ(L"", rev.m_Description);

	rev = refMap[L"refs/heads/subdir/branch"];
	EXPECT_STREQ(L"31ff87c86e9f6d3853e438cb151043f30f09029a", rev.m_CommitHash.ToString());
	EXPECT_STREQ(L"Sven Strickroth", rev.GetAuthorName());
	EXPECT_STREQ(L"2015-03-16 12:52:29", rev.GetAuthorDate().FormatGmt(L"%Y-%m-%d %H:%M:%S")); // used here, because author and commit time differ
	EXPECT_STREQ(L"Several actions", rev.GetSubject());
	EXPECT_STREQ(L"", rev.m_UpstreamRef);
	EXPECT_STREQ(L"multi\nline", rev.m_Description);

	refMap.clear();
	EXPECT_EQ(0, GitRevRefBrowser::GetGitRevRefMap(refMap, 0, err, [](const CString& refName) { return CStringUtils::StartsWith(refName, L"refs/heads/"); }));
	EXPECT_STREQ(L"", err);
	EXPECT_EQ(6U, refMap.size());
	EXPECT_TRUE(refMap.find(L"refs/heads/master") != refMap.end());
	for (auto it = refMap.cbegin(); it != refMap.cend(); ++it)
		EXPECT_TRUE(CStringUtils::StartsWith(it->first, L"refs/heads/"));

	refMap.clear();
	EXPECT_EQ(0, GitRevRefBrowser::GetGitRevRefMap(refMap, 1, err));
	EXPECT_STREQ(L"", err);
	EXPECT_EQ(6U, refMap.size());
	for (const auto& branch : { L"refs/heads/master", L"refs/heads/master2", L"refs/remotes/origin/master", L"refs/tags/all-files-signed", L"refs/tags/also-signed", L"refs/tags/normal-tag" })
		EXPECT_TRUE(refMap.find(branch) != refMap.end());

	refMap.clear();
	EXPECT_EQ(0, GitRevRefBrowser::GetGitRevRefMap(refMap, 2, err));
	EXPECT_STREQ(L"", err);
	EXPECT_EQ(6U, refMap.size());
	EXPECT_TRUE(refMap.find(L"refs/heads/master") == refMap.end());
	for (const auto& branch : { L"refs/heads/forconflict", L"refs/heads/signed-commit", L"refs/heads/simple-conflict", L"refs/heads/subdir/branch", L"refs/notes/commits", L"refs/stash" })
		EXPECT_TRUE(refMap.find(branch) != refMap.end());
}