You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2025/08/01 09:52:50 UTC

(maven-scm) branch master updated: JGit: Propagate exceptions when pushing tags/branches (#1271)

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-scm.git


The following commit(s) were added to refs/heads/master by this push:
     new 3e6a34e5e JGit: Propagate exceptions when pushing tags/branches (#1271)
3e6a34e5e is described below

commit 3e6a34e5e50a9a219709c43a2545fa5e015147a5
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Fri Aug 1 11:52:45 2025 +0200

    JGit: Propagate exceptions when pushing tags/branches (#1271)
    
    Add tests for all Git providers for failing push operations
    This closes #1253
---
 .../maven/scm/provider/git/GitScmTestUtils.java    | 54 ++++++++++++++++++++++
 .../command/branch/GitBranchCommandTckTest.java    | 18 ++++++++
 .../git/command/tag/GitTagCommandTckTest.java      | 18 ++++++++
 .../git/command/untag/GitUntagCommandTckTest.java  | 29 ++++++++++++
 .../scm/provider/git/jgit/command/JGitUtils.java   | 15 ++++--
 .../provider/git/jgit/command/PushException.java   | 40 ++++++++++++++++
 .../git/jgit/command/branch/JGitBranchCommand.java | 14 +++++-
 .../jgit/command/checkin/JGitCheckInCommand.java   | 31 +++++--------
 .../git/jgit/command/tag/JGitTagCommand.java       |  7 +++
 .../git/jgit/command/untag/JGitUntagCommand.java   | 14 +++++-
 10 files changed, 214 insertions(+), 26 deletions(-)

diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/GitScmTestUtils.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/GitScmTestUtils.java
index 2a4ce35e4..ecbe42ab2 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/GitScmTestUtils.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/GitScmTestUtils.java
@@ -102,4 +102,58 @@ public static void setDefaultGitConfig(File repositoryRootFile) {
             e.printStackTrace();
         }
     }
+
+    /**
+     * Sets up a pre-receive git hook that rejects all commits for the given repository (server-side).
+     * This is useful for testing scenarios where you want to simulate a repository
+     * that doesn't allow any new commits.
+     * This hook is <a href="https://github.com/eclipse-jgit/jgit/issues/192">not supported by JGit</a>.
+     *
+     *
+     * @param repositoryRootFile the root directory of the git repository
+     * @throws IOException if there's an error creating or writing the hook file
+     */
+    public static void setupRejectAllCommitsPreReceiveHook(File repositoryRootFile) throws IOException {
+        setupRejectAllCommitsHook(repositoryRootFile, true, "pre-receive");
+    }
+
+    /**
+     * Sets up a pre-push git hook that rejects all commits for the given repository (client-side).
+     * This is useful for testing scenarios where you want to simulate a repository
+     * that doesn't allow any new commits.
+     *
+     * @param workspaceRoot the root directory of the git working copy
+     * @throws IOException if there's an error creating or writing the hook file
+     */
+    public static void setupRejectAllCommitsPrePushHook(File workspaceRoot) throws IOException {
+        setupRejectAllCommitsHook(workspaceRoot, false, "pre-push");
+    }
+
+    private static void setupRejectAllCommitsHook(
+            File repositoryOrWorkspaceRootFile, boolean isServerSide, String hookName) throws IOException {
+        File hooksDir;
+        if (!isServerSide) {
+            // For client-side hooks, we use the .git/hooks directory
+            hooksDir = new File(repositoryOrWorkspaceRootFile, ".git/hooks");
+        } else {
+            // For server-side hooks, we use the hooks directory directly
+            hooksDir = new File(repositoryOrWorkspaceRootFile, "hooks");
+        }
+        if (!hooksDir.exists() && !hooksDir.mkdirs()) {
+            throw new IOException("Failed to create hooks directory: " + hooksDir.getAbsolutePath());
+        }
+
+        File preReceiveHook = new File(hooksDir, hookName);
+        try (FileWriter fw = new FileWriter(preReceiveHook)) {
+            fw.write("#!/bin/sh\n");
+            fw.write("# Pre-receive hook that rejects all commits\n");
+            fw.write("echo \"Error: This repository is configured to reject all commits\"\n");
+            fw.write("exit 1\n");
+        }
+
+        // Make the hook executable (on Unix-like systems)
+        if (!preReceiveHook.setExecutable(true)) {
+            throw new IOException("Could not make pre-receive hook executable at: " + preReceiveHook.getAbsolutePath());
+        }
+    }
 }
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/branch/GitBranchCommandTckTest.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/branch/GitBranchCommandTckTest.java
index 0dd33b0ec..68941bdc1 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/branch/GitBranchCommandTckTest.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/branch/GitBranchCommandTckTest.java
@@ -20,10 +20,15 @@
 
 import java.io.File;
 
+import org.apache.maven.scm.ScmFileSet;
+import org.apache.maven.scm.command.branch.BranchScmResult;
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
 import org.apache.maven.scm.provider.git.GitScmTestUtils;
 import org.apache.maven.scm.repository.ScmRepository;
 import org.apache.maven.scm.tck.command.branch.BranchCommandTckTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
@@ -43,4 +48,17 @@ protected CheckOutScmResult checkOut(File workingDirectory, ScmRepository reposi
             GitScmTestUtils.setDefaultGitConfig(workingDirectory);
         }
     }
+
+    @Test
+    public void testPushBranchRejected() throws Exception {
+        String branch = getBranch();
+
+        GitScmTestUtils.setupRejectAllCommitsPrePushHook(getWorkingCopy());
+        @SuppressWarnings("deprecation")
+        BranchScmResult branchResult = getScmManager()
+                .getProviderByUrl(getScmUrl())
+                .branch(getScmRepository(), new ScmFileSet(getWorkingCopy()), branch);
+
+        assertFalse("Branch should not have been pushed", branchResult.isSuccess());
+    }
 }
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/tag/GitTagCommandTckTest.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/tag/GitTagCommandTckTest.java
index 21640a5f9..b151574de 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/tag/GitTagCommandTckTest.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/tag/GitTagCommandTckTest.java
@@ -20,10 +20,15 @@
 
 import java.io.File;
 
+import org.apache.maven.scm.ScmFileSet;
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
+import org.apache.maven.scm.command.tag.TagScmResult;
 import org.apache.maven.scm.provider.git.GitScmTestUtils;
 import org.apache.maven.scm.repository.ScmRepository;
 import org.apache.maven.scm.tck.command.tag.TagCommandTckTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
 
 /**
  * @author <a href="mailto:struberg@yahoo.de">Mark Struberg</a>
@@ -43,4 +48,17 @@ protected CheckOutScmResult checkOut(File workingDirectory, ScmRepository reposi
             GitScmTestUtils.setDefaultGitConfig(workingDirectory);
         }
     }
+
+    @Test
+    public void testPushTagRejected() throws Exception {
+        String tag = getTagName();
+
+        GitScmTestUtils.setupRejectAllCommitsPrePushHook(getWorkingCopy());
+        @SuppressWarnings("deprecation")
+        TagScmResult tagResult = getScmManager()
+                .getProviderByUrl(getScmUrl())
+                .tag(getScmRepository(), new ScmFileSet(getWorkingCopy()), tag);
+
+        assertFalse("Tag should not have been pushed", tagResult.isSuccess());
+    }
 }
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/untag/GitUntagCommandTckTest.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/untag/GitUntagCommandTckTest.java
index 652460cb2..acf5abed3 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/untag/GitUntagCommandTckTest.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-gittest/src/main/java/org/apache/maven/scm/provider/git/command/untag/GitUntagCommandTckTest.java
@@ -20,10 +20,20 @@
 
 import java.io.File;
 
+import org.apache.maven.scm.CommandParameter;
+import org.apache.maven.scm.CommandParameters;
+import org.apache.maven.scm.ScmFileSet;
+import org.apache.maven.scm.ScmTagParameters;
 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
+import org.apache.maven.scm.command.tag.TagScmResult;
+import org.apache.maven.scm.command.untag.UntagScmResult;
+import org.apache.maven.scm.provider.ScmProvider;
 import org.apache.maven.scm.provider.git.GitScmTestUtils;
 import org.apache.maven.scm.repository.ScmRepository;
 import org.apache.maven.scm.tck.command.untag.UntagCommandTckTest;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
 
 /** {@inheritDoc} */
 public abstract class GitUntagCommandTckTest extends UntagCommandTckTest {
@@ -40,4 +50,23 @@ protected CheckOutScmResult checkOut(File workingDirectory, ScmRepository reposi
             GitScmTestUtils.setDefaultGitConfig(workingDirectory);
         }
     }
+
+    @Test
+    public void testPushTagDeletionRejected() throws Exception {
+        String tag = getTagName();
+        ScmProvider scmProvider = getScmManager().getProviderByUrl(getScmUrl());
+        ScmRepository scmRepository = getScmRepository();
+        ScmFileSet files = new ScmFileSet(getWorkingCopy());
+        TagScmResult tagResult = scmProvider.tag(scmRepository, files, tag, new ScmTagParameters());
+
+        assertResultIsSuccess(tagResult);
+
+        GitScmTestUtils.setupRejectAllCommitsPrePushHook(getWorkingCopy());
+        CommandParameters params = new CommandParameters();
+        params.setString(CommandParameter.TAG_NAME, tag);
+
+        UntagScmResult untagResult = scmProvider.untag(scmRepository, files, params);
+
+        assertFalse("Tag deletion should not have been pushed", untagResult.isSuccess());
+    }
 }
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java
index deac415fa..17a0e6664 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/JGitUtils.java
@@ -166,17 +166,26 @@ public static Iterable<PushResult> push(
             Git git,
             GitScmProviderRepository repo,
             RefSpec refSpec,
+            Set<RemoteRefUpdate.Status> successfulStatuses,
             Optional<TransportConfigCallback> transportConfigCallback)
-            throws GitAPIException {
+            throws PushException {
         CredentialsProvider credentials = prepareSession(git, repo);
         PushCommand command = git.push().setRefSpecs(refSpec).setCredentialsProvider(credentials);
         transportConfigCallback.ifPresent(command::setTransportConfigCallback);
 
-        Iterable<PushResult> pushResultList = command.call();
+        Iterable<PushResult> pushResultList;
+        try {
+            pushResultList = command.call();
+        } catch (GitAPIException e) {
+            throw new PushException(repo.getPushUrlWithMaskedPassword(), e);
+        }
         for (PushResult pushResult : pushResultList) {
             Collection<RemoteRefUpdate> ru = pushResult.getRemoteUpdates();
             for (RemoteRefUpdate remoteRefUpdate : ru) {
-                LOGGER.info(remoteRefUpdate.getStatus() + " - " + remoteRefUpdate);
+                if (!successfulStatuses.contains(remoteRefUpdate.getStatus())) {
+                    throw new PushException(repo.getPushUrlWithMaskedPassword(), remoteRefUpdate);
+                }
+                LOGGER.debug("Push succeeded {}", remoteRefUpdate);
             }
         }
         return pushResultList;
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PushException.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PushException.java
new file mode 100644
index 000000000..35d2ba263
--- /dev/null
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/PushException.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.scm.provider.git.jgit.command;
+
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+
+/**
+ * Exception thrown when a push operation fails in JGit.
+ * This may either be triggered by an exception during the push operation or
+ * by a failed update of a remote reference.
+ */
+public class PushException extends Exception {
+
+    private static final long serialVersionUID = 1L;
+
+    public PushException(String url, RemoteRefUpdate update) {
+        super("Failed to push reference to " + url + ": " + update);
+    }
+
+    public PushException(String url, GitAPIException e) {
+        super("Failed to push reference to " + url + ": " + e.getMessage(), e);
+    }
+}
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/branch/JGitBranchCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/branch/JGitBranchCommand.java
index 05ad6986c..30c238bf6 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/branch/JGitBranchCommand.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/branch/JGitBranchCommand.java
@@ -19,6 +19,7 @@
 package org.apache.maven.scm.provider.git.jgit.command.branch;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -38,6 +39,7 @@
 import org.apache.maven.scm.provider.git.jgit.command.CustomizableSshSessionFactoryCommand;
 import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback;
 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
+import org.apache.maven.scm.provider.git.jgit.command.PushException;
 import org.apache.maven.scm.provider.git.jgit.command.ScmProviderAwareSshdSessionFactory;
 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
 import org.eclipse.jgit.api.Git;
@@ -49,6 +51,7 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.slf4j.Logger;
 
@@ -85,8 +88,9 @@ protected ScmResult executeBranchCommand(
         if (!fileSet.getFileList().isEmpty()) {
             throw new ScmException("This provider doesn't support branching subsets of a directory");
         }
-
-        try (Git git = JGitUtils.openRepo(fileSet.getBasedir())) {
+        Git git = null;
+        try {
+            git = JGitUtils.openRepo(fileSet.getBasedir());
             Ref branchResult = git.branchCreate().setName(branch).call();
             logger.info("created [" + branchResult.getName() + "]");
 
@@ -105,6 +109,7 @@ protected ScmResult executeBranchCommand(
                         git,
                         (GitScmProviderRepository) repo,
                         new RefSpec(Constants.R_HEADS + branch),
+                        EnumSet.of(RemoteRefUpdate.Status.OK, RemoteRefUpdate.Status.UP_TO_DATE),
                         Optional.of(transportConfigCallback));
             }
 
@@ -126,8 +131,13 @@ protected ScmResult executeBranchCommand(
 
             return new BranchScmResult("JGit branch", files);
 
+        } catch (PushException e) {
+            logger.debug("Failed to push branch", e);
+            return new BranchScmResult("JGit branch", "Failed to push changes: " + e.getMessage(), "", false);
         } catch (Exception e) {
             throw new ScmException("JGit branch failed!", e);
+        } finally {
+            JGitUtils.closeRepo(git);
         }
     }
 
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java
index 5b5ae5930..34b4053b6 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java
@@ -22,6 +22,7 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -41,6 +42,7 @@
 import org.apache.maven.scm.provider.git.jgit.command.CustomizableSshSessionFactoryCommand;
 import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback;
 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
+import org.apache.maven.scm.provider.git.jgit.command.PushException;
 import org.apache.maven.scm.provider.git.jgit.command.ScmProviderAwareSshdSessionFactory;
 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
 import org.eclipse.jgit.api.AddCommand;
@@ -51,7 +53,6 @@
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.UserConfig;
 import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.transport.PushResult;
 import org.eclipse.jgit.transport.RefSpec;
 import org.eclipse.jgit.transport.RemoteRefUpdate;
 import org.slf4j.Logger;
@@ -176,23 +177,18 @@ public CheckInScmResult executeCommand(ScmProviderRepository repo, ScmFileSet fi
                 TransportConfigCallback transportConfigCallback = new JGitTransportConfigCallback(
                         sshSessionFactorySupplier.apply((GitScmProviderRepository) repo, logger));
 
-                Iterable<PushResult> pushResultList = JGitUtils.push(
-                        git, (GitScmProviderRepository) repo, refSpec, Optional.of(transportConfigCallback));
-
-                for (PushResult pushResult : pushResultList) {
-                    for (RemoteRefUpdate remoteRefUpdate : pushResult.getRemoteUpdates()) {
-                        if (!isSuccessStatus(remoteRefUpdate.getStatus())) {
-                            return new CheckInScmResult(
-                                    "JGit checkin",
-                                    "The git-push command failed, with status: " + remoteRefUpdate.getStatus(),
-                                    remoteRefUpdate.getMessage(),
-                                    false);
-                        }
-                    }
-                }
+                JGitUtils.push(
+                        git,
+                        (GitScmProviderRepository) repo,
+                        refSpec,
+                        EnumSet.of(RemoteRefUpdate.Status.OK, RemoteRefUpdate.Status.UP_TO_DATE),
+                        Optional.of(transportConfigCallback));
             }
 
             return new CheckInScmResult("JGit checkin", checkedInFiles);
+        } catch (PushException e) {
+            logger.debug("Failed to push commits", e);
+            return new CheckInScmResult("JGit checkin", "Failed to push changes: " + e.getMessage(), "", false);
         } catch (Exception e) {
             throw new ScmException("JGit checkin failure!", e);
         } finally {
@@ -212,11 +208,6 @@ protected CheckInScmResult executeCheckInCommand(
         return executeCommand(repo, fileSet, parameters);
     }
 
-    private boolean isSuccessStatus(RemoteRefUpdate.Status remoteRefUpdateStatus) {
-        return remoteRefUpdateStatus == RemoteRefUpdate.Status.OK
-                || remoteRefUpdateStatus == RemoteRefUpdate.Status.UP_TO_DATE;
-    }
-
     private static final class UserInfo {
 
         final String name;
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/tag/JGitTagCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/tag/JGitTagCommand.java
index 075ed4b32..94867a6d3 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/tag/JGitTagCommand.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/tag/JGitTagCommand.java
@@ -19,6 +19,7 @@
 package org.apache.maven.scm.provider.git.jgit.command.tag;
 
 import java.util.ArrayList;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.function.BiFunction;
@@ -36,6 +37,7 @@
 import org.apache.maven.scm.provider.git.jgit.command.CustomizableSshSessionFactoryCommand;
 import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback;
 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
+import org.apache.maven.scm.provider.git.jgit.command.PushException;
 import org.apache.maven.scm.provider.git.jgit.command.ScmProviderAwareSshdSessionFactory;
 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
 import org.eclipse.jgit.api.Git;
@@ -45,6 +47,7 @@
 import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.slf4j.Logger;
 
@@ -111,6 +114,7 @@ public ScmResult executeTagCommand(
                         git,
                         (GitScmProviderRepository) repo,
                         new RefSpec(Constants.R_TAGS + escapedTagName),
+                        EnumSet.of(RemoteRefUpdate.Status.OK, RemoteRefUpdate.Status.UP_TO_DATE),
                         Optional.of(transportConfigCallback));
             }
 
@@ -131,6 +135,9 @@ public ScmResult executeTagCommand(
             walk.close();
 
             return new TagScmResult("JGit tag", taggedFiles);
+        } catch (PushException e) {
+            logger.debug("Failed to push tag", e);
+            return new TagScmResult("JGit tag", "Failed to push tag: " + e.getMessage(), "", false);
         } catch (Exception e) {
             throw new ScmException("JGit tag failure!", e);
         } finally {
diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/untag/JGitUntagCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/untag/JGitUntagCommand.java
index 6fea4bff3..2a0e22d75 100644
--- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/untag/JGitUntagCommand.java
+++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/untag/JGitUntagCommand.java
@@ -19,6 +19,7 @@
 package org.apache.maven.scm.provider.git.jgit.command.untag;
 
 import java.util.Collection;
+import java.util.EnumSet;
 import java.util.Optional;
 import java.util.function.BiFunction;
 
@@ -33,6 +34,7 @@
 import org.apache.maven.scm.provider.git.jgit.command.CustomizableSshSessionFactoryCommand;
 import org.apache.maven.scm.provider.git.jgit.command.JGitTransportConfigCallback;
 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
+import org.apache.maven.scm.provider.git.jgit.command.PushException;
 import org.apache.maven.scm.provider.git.jgit.command.ScmProviderAwareSshdSessionFactory;
 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
 import org.eclipse.jgit.api.Git;
@@ -88,7 +90,14 @@ protected ScmResult executeUntagCommand(
                 logger.info("push delete tag [" + escapedTagName + "] to remote...");
 
                 Iterable<PushResult> pushResultList = JGitUtils.push(
-                        git, (GitScmProviderRepository) repository, refSpec, Optional.of(transportConfigCallback));
+                        git,
+                        (GitScmProviderRepository) repository,
+                        refSpec,
+                        EnumSet.of(
+                                RemoteRefUpdate.Status.OK,
+                                RemoteRefUpdate.Status.UP_TO_DATE,
+                                RemoteRefUpdate.Status.NON_EXISTING),
+                        Optional.of(transportConfigCallback));
                 if (logger.isInfoEnabled()) {
                     for (PushResult pushResult : pushResultList) {
                         Collection<RemoteRefUpdate> ru = pushResult.getRemoteUpdates();
@@ -100,6 +109,9 @@ protected ScmResult executeUntagCommand(
             }
 
             return new UntagScmResult("JGit tagDelete");
+        } catch (PushException e) {
+            logger.debug("Failed to push tag deletion", e);
+            return new UntagScmResult("JGit tagDelete", "Failed to push tag deletion: " + e.getMessage(), "", false);
         } catch (Exception e) {
             throw new ScmException("JGit tagDelete failure!", e);
         } finally {