diff --git a/app/services/git/providers/abstract.rb b/app/services/git/providers/abstract.rb
index 255080dc12a5a930fc3084bb6ac80f2c269325f5..90b9081a91d3518646c75dfc3bd4a24088f62b6b 100644
--- a/app/services/git/providers/abstract.rb
+++ b/app/services/git/providers/abstract.rb
@@ -9,4 +9,10 @@ class Git::Providers::Abstract
   def valid?
     repository.present? && access_token.present?
   end
+
+  protected
+
+  def batch
+    @batch ||= []
+  end
 end
diff --git a/app/services/git/providers/github.rb b/app/services/git/providers/github.rb
index df1ce2f957a12be091aff98b4fa5b74c7b59f029..4b123493862ac7e23cdc93c442396e1b380dce7b 100644
--- a/app/services/git/providers/github.rb
+++ b/app/services/git/providers/github.rb
@@ -60,10 +60,6 @@ class Git::Providers::Github < Git::Providers::Abstract
     @client ||= Octokit::Client.new access_token: access_token
   end
 
-  def batch
-    @batch ||= []
-  end
-
   def default_branch
     @default_branch ||= client.repo(repository)[:default_branch]
   end
diff --git a/app/services/git/providers/gitlab.rb b/app/services/git/providers/gitlab.rb
index cc8b214a88617869b6e477923c8ebeb24d6d11db..efb7433d21a90b623a66bca69fe9bca159d1a417 100644
--- a/app/services/git/providers/gitlab.rb
+++ b/app/services/git/providers/gitlab.rb
@@ -1,16 +1,73 @@
 class Git::Providers::Gitlab < Git::Providers::Abstract
   def create_file(path, content)
+    batch << {
+      action: 'create',
+      file_path: path,
+      content: content
+    }
   end
 
   def update_file(path, previous_path, content)
+    file = find_in_tree previous_path
+    return if file.nil?
+    if previous_path != path
+      batch << {
+        action: 'move',
+        file_path: path,
+        previous_path: previous_path
+      }
+    end
+    batch << {
+      action: 'update',
+      file_path: path,
+      content: content
+    }
   end
 
   def destroy_file(path)
+    file = find path
+    return if file.nil?
+    batch << {
+      action: 'delete',
+      file_path: path,
+    }
   end
 
   def push(commit_message)
+    return if !valid? || batch.empty?
+    client.create_commit  repository,
+                          'main',
+                          commit_message,
+                          batch
+    true
   end
 
+  # https://gitlab.com/gitlab-org/gitlab/-/issues/23504
   def git_sha(path)
+    begin
+      file = find path
+      sha = file['content_sha256']
+    rescue
+      sha = nil
+    end
+    sha
   end
+
+  protected
+
+  def client
+    @client ||= Gitlab.client(
+      endpoint: 'https://gitlab.com/api/v4',
+      private_token: access_token
+    )
+  end
+
+  def find(path)
+    client.get_file repository,
+                    path,
+                    'main'
+  rescue
+    nil
+  end
+
 end