diff --git a/src/application/GitRepository.ts b/src/application/GitRepository.ts index e7e5834..6b01747 100644 --- a/src/application/GitRepository.ts +++ b/src/application/GitRepository.ts @@ -4,6 +4,7 @@ import { join } from 'path' import { readFile } from 'fs' import Git from '../models/Git' import Submodule from '../models/Submodule' +import Branch from '../models/Branch' import Logger from '../UI/Logger' import Status from '../UI/Status' import StatusBar from '../UI/StatusBar' @@ -470,6 +471,37 @@ export default class GitRepository { }) } + /** + * Get the list of branches that conatining current commit + * @param gitModel Git-Model of Submodule + */ + static async getBranchesContain(gitModel: Git): Promise { + let simplegit = GitRepository.getSimplegit(gitModel.getRelativePath()) + const branches_local = await simplegit.branch(['--contains', gitModel.getBranch()]) + const branches_remote = await simplegit.branch(['--remote', '--contains', gitModel.getBranch()]) + let branches : Branch[] = [] + let branches_local_names : string[] = [] + let discardfirst : boolean = branches_local.detached + branches_local.all.forEach((key: any) => { + // Discard the first local branch if detached (it is our detached branch) + if (discardfirst) { + discardfirst = false + } else { + branches.push(new Branch(branches_local.branches[key].name, branches_local.branches[key].commit)) + branches_local_names.push(branches_local.branches[key].name) + } + }) + branches_remote.all.forEach((key: any) => { + // Get the branch name by removing the first part before slash which is the origin + let name = branches_remote.branches[key].name.split("/",2)[1] + // Make sure that we don't add twice a remote branch and local branch + if (!branches_local_names.includes(name)) { + branches.push(new Branch(name, branches_remote.branches[key].commit)) + } + }) + return branches + } + /*******************************************************************************************/ /* PULL */ /*******************************************************************************************/ diff --git a/src/handlers/git/branch_changed/DetectDetachedHead.handler.ts b/src/handlers/git/branch_changed/DetectDetachedHead.handler.ts index 0bcd3bb..ad05eb3 100644 --- a/src/handlers/git/branch_changed/DetectDetachedHead.handler.ts +++ b/src/handlers/git/branch_changed/DetectDetachedHead.handler.ts @@ -66,44 +66,41 @@ export default class DetectDetachedHead extends ChangeHandler { * finds the corresponding Branch for a Commit-Hash */ private static getRealBranchForHash = async (gitModel: Git): Promise => { - // the first one in the list is the current "detached HEAD" - const branches = gitModel.getLocalBranches().filter((branch, index) => index > 1) - const current = gitModel.getBranch() - - const realBranches: string[] = [] - branches.forEach((branch: Branch) => { - if (current === branch.getCommit() || current === branch.getName()) { - realBranches.push(branch.getName()) - } - }) - - if (realBranches.length) { - if (realBranches.length === 1) { - return realBranches[0] - } - + // Get the list of branches that contain the specified commit + const branches = await GitRepository.getBranchesContain(gitModel) + // If there is only one, we have found it + if (branches.length === 1) { + return branches[0].getName() + } + // Otherwise, if we have many options ... + if (branches.length) { + // Create a list with the branches names + const branches_names: string[] = [] + branches.forEach((branch: Branch) => { + branches_names.push(branch.getName()) + }) + // Check if any of them match with the configured one in .gitmodules if (gitModel.getMainRepositoryPath()) { const configuredBranch = await GitRepository.getConfiguredBranchForSubmodule(gitModel) - if (configuredBranch && realBranches.includes(configuredBranch)) { + if (configuredBranch && branches_names.includes(configuredBranch)) { return configuredBranch } - - const options: QuickPickOption[] = realBranches.map((branch) => new QuickPickOption(branch, branch)) - - const selectedBranch = await QuickPick.showQuickPick('choose the branch to check out', ...options) - if (selectedBranch) { - return selectedBranch - } + } + // Otherwise ask the user + const options: QuickPickOption[] = branches_names.map((branch) => new QuickPickOption(branch, branch)) + const selectedBranch = await QuickPick.showQuickPick('choose the branch to check out', ...options) + if (selectedBranch) { + return selectedBranch } } - + // If no branch contains the current commit, just warn the user + const current = gitModel.getBranch() Logger.showError( `could not find branch for '${current}' ${ !gitModel.isRootGit() ? ` in Submodule '${gitModel.getRelativePath()}'` : '' }. You have to checkout the branch manually.`, true, ) - return '' } }