When automating Git operations across distributed systems, Ansible users often hit a roadblock with direct git commands. The hanging issue typically occurs because:
- SSH connections time out during lengthy git operations
- Password prompts aren't handled properly
- The script module doesn't manage interactive sessions well
Instead of raw scripts, consider these native approaches:
1. Using the git module for pull operations:
- name: Perform git pull on remote host
ansible.builtin.git:
repo: 'https://github.com/user/repo.git'
dest: /path/to/repo
version: main
update: yes
accept_hostkey: yes
2. For push operations (requires credential handling):
- name: Configure git credentials
become: false
ansible.builtin.shell: |
git config --global credential.helper store
echo "https://{{ git_username }}:{{ git_token }}@github.com" > ~/.git-credentials
args:
creates: ~/.git-credentials
- name: Execute git push
ansible.builtin.shell: |
cd /path/to/repo && \
git add . && \
git commit -m "Automated commit by Ansible" && \
git push origin main
For private repositories using SSH keys:
- name: Deploy SSH key for git access
ansible.builtin.copy:
src: ~/.ssh/id_rsa
dest: /home/remote_user/.ssh/id_rsa
mode: '0600'
- name: Add github.com to known_hosts
ansible.builtin.shell: |
ssh-keyscan github.com >> ~/.ssh/known_hosts
- name: Pull via SSH
ansible.builtin.git:
repo: git@github.com:user/repo.git
dest: /path/to/repo
key_file: /home/remote_user/.ssh/id_rsa
If you still encounter hanging:
- Add
async
andpoll
parameters to prevent timeouts - Set
GIT_SSH_COMMAND="ssh -o ConnectTimeout=30"
in environment variables - Consider using Ansible vault for credential security
- name: Git synchronization workflow
hosts: webservers
vars:
repo_path: /var/www/app
tasks:
- name: Ensure repo directory exists
ansible.builtin.file:
path: "{{ repo_path }}"
state: directory
- name: Clone or update repository
ansible.builtin.git:
repo: '{{ git_repository }}'
dest: "{{ repo_path }}"
version: '{{ git_branch }}'
update: yes
register: git_result
async: 300
poll: 10
- name: Notify on changes
ansible.builtin.debug:
msg: "Repository was updated"
when: git_result.changed
When managing infrastructure as code, there are scenarios where you need to update git repositories across multiple servers. While Ansible has excellent modules for file manipulation and package management, native git operations require careful implementation.
The most common pitfall is using the command
or shell
module directly with git commands. This often hangs because:
# Problematic approach (may hang)
- name: Bad git pull example
shell: git pull origin main
This fails because git might prompt for credentials or encounter SSH host verification.
Using the git Module Properly
Ansible's git
module actually works well when configured correctly:
- name: Clone or update repository
git:
repo: 'git@github.com:user/repo.git'
dest: /path/to/repo
version: main
accept_hostkey: yes
key_file: /path/to/private_key
update: yes
SSH Agent Forwarding Approach
For pushing changes, SSH agent forwarding is often the cleanest solution:
- name: Configure SSH agent forwarding
set_fact:
ansible_ssh_common_args: '-o ForwardAgent=yes'
- name: Git push changes
shell: |
cd /path/to/repo
git config --global user.email "ci@example.com"
git config --global user.name "CI Server"
git add .
git commit -m "Automated update"
git push origin main
Deploy Key Alternative
For production environments, deploy keys provide better security:
- name: Set up deploy key
copy:
src: files/deploy_key
dest: /home/user/.ssh/id_rsa
mode: '0600'
- name: Update repository using deploy key
git:
repo: 'git@github.com:user/repo.git'
dest: /path/to/repo
version: main
key_file: /home/user/.ssh/id_rsa
force: yes
When dealing with submodules or complex workflows, consider:
- name: Recursive git operations
shell: |
cd /path/to/repo
git submodule update --init --recursive
git pull --recurse-submodules
args:
executable: /bin/bash
For large repositories, shallow clones can save time:
- name: Shallow clone
git:
repo: 'git@github.com:user/repo.git'
dest: /path/to/repo
depth: 1
single_branch: yes