docs: @Override
      public void execute() throws MojoExecutionException, MojoFailureException {
          validateConfiguration();
  
          try {
              // check uncommitted changes
              checkUncommittedChanges();
  
              String featureBranchName = null;
              if (settings.isInteractiveMode()) {
                  featureBranchName = promptBranchName();
              } else if (StringUtils.isNotBlank(featureName)) {
                  final String branch = gitFlowConfig.getFeatureBranchPrefix()
                          + featureName;
                  if (!gitCheckBranchExists(branch)) {
                      throw new MojoFailureException("Feature branch with name '"
                              + branch
                              + "' doesn't exist. Cannot finish feature.");
                  }
                  featureBranchName = branch;
              }
  
              if (StringUtils.isBlank(featureBranchName)) {
                  throw new MojoFailureException(
                          "Feature branch name to finish is blank.");
              }
  
              // fetch and check remote
              if (fetchRemote) {
                  gitFetchRemoteAndCompare(featureBranchName);
  
                  gitFetchRemoteAndCompare(gitFlowConfig.getDevelopmentBranch());
              }
  
              if (!skipTestProject) {
                  // git checkout feature/...
                  gitCheckout(featureBranchName);
  
                  // mvn clean test
                  mvnCleanTest();
              }
  
              // git checkout develop
              gitCheckout(gitFlowConfig.getDevelopmentBranch());
  
              if (featureSquash) {
                  // git merge --squash feature/...
                  gitMergeSquash(featureBranchName);
                  gitCommit(featureBranchName);
              } else {
                  // git merge --no-ff feature/...
                  gitMergeNoff(featureBranchName);
              }
  
              // get current project version from pom
              final String currentVersion = getCurrentProjectVersion();
  
              final String featName = featureBranchName
                      .replaceFirst(gitFlowConfig.getFeatureBranchPrefix(), "");
  
              if (currentVersion.contains("-" + featName)) {
                  final String version = currentVersion
                          .replaceFirst("-" + featName, "");
  
                  // mvn versions:set -DnewVersion=... -DgenerateBackupPoms=false
                  mvnSetVersions(version);
  
                  Map<String, String> properties = new HashMap<String, String>();
                  properties.put("version", version);
                  properties.put("featureName", featName);
  
                  // git commit -a -m updating versions for development branch
                  gitCommit(commitMessages.getFeatureFinishMessage(), properties);
              }
  
              if (installProject) {
                  // mvn clean install
                  mvnCleanInstall();
              }
  
              if (pushRemote) {
                  gitPush(gitFlowConfig.getDevelopmentBranch(), false);
  
                  if (!keepBranch) {
                      gitPushDelete(featureBranchName);
                  }
              }
  
              if (!keepBranch) {
                  if (featureSquash) {
                      // git branch -D feature/...
                      gitBranchDeleteForce(featureBranchName);
                  } else {
                      // git branch -d feature/...
                      gitBranchDelete(featureBranchName);
                  }
              }
          } catch (CommandLineException e) {
              throw new MojoFailureException("feature-finish", e);
          }
      }