Git Integration: Fugitive y Herramientas
Git es fundamental en el desarrollo moderno, y Vim puede integrarse perfectamente con Git para crear un workflow eficiente sin salir del editor. En este capítulo aprenderás a dominar Git desde Vim.
🌟 Vim-Fugitive: Git en Vim
Fugitive es el plugin de Git más poderoso para Vim, creado por Tim Pope. Transforma Vim en un cliente Git completo.
Instalación y configuración básica
" Instalación con vim-plug
Plug 'tpope/vim-fugitive'
" Configuración básica
set diffopt+=vertical " Diffs verticales por defecto
" Mapeos básicos para Fugitive
nnoremap <Leader>gs :Git status<CR>
nnoremap <Leader>gc :Git commit<CR>
nnoremap <Leader>gp :Git push<CR>
nnoremap <Leader>gl :Git log --oneline<CR>
nnoremap <Leader>gd :Gdiff<CR>
nnoremap <Leader>gb :Git blame<CR>
📊 Git Status y Navegación
Comando :Git status
:Git status " O simplemente :G
Navegación en la ventana de status
<Enter> " Abrir archivo/diff
- " Stage/unstage archivo
cc " Commit
ca " Commit --amend
ce " Commit --amend --no-edit
cw " Commit --amend --only
U " Checkout (discard changes)
s " Stage archivo
u " Unstage archivo
X " Discard changes in archivo
= " Toggle inline diff
> " Show more context
< " Show less context
Ejemplo de workflow básico
" 1. Ver status
:G
" 2. Stage archivos (en la ventana de status)
" Usar 's' en cada archivo o '-' para toggle
" 3. Commit
" Presionar 'cc' en la ventana de status
" 4. Push
:Git push
🔍 Comandos Esenciales de Fugitive
Información del repositorio
:Git status " Status del repositorio
:Git log " Log de commits
:Git log --oneline " Log compacto
:Git log -p " Log con diffs
:Git log --graph " Log con gráfico ASCII
:Git show <commit> " Mostrar commit específico
:Git blame " Blame del archivo actual
Gestión de cambios
:Gdiff " Diff del archivo actual
:Gdiff HEAD~1 " Diff con commit anterior
:Gdiff main " Diff con rama main
:Git add % " Stage archivo actual
:Git add . " Stage todos los archivos
:Git reset % " Unstage archivo actual
:Git checkout % " Discard cambios del archivo actual
Commits y ramas
:Git commit " Commit interactivo
:Git commit -m "msg" " Commit con mensaje
:Git commit --amend " Amend último commit
:Git branch " Listar ramas
:Git checkout <rama> " Cambiar de rama
:Git checkout -b <nueva_rama> " Crear y cambiar rama
:Git merge <rama> " Merge rama
🔄 Workflows Avanzados
Resolución de conflictos
" Durante un merge con conflictos
:Git status " Ver archivos en conflicto
" Abrir archivo con conflicto
:Gdiffsplit! " Three-way diff
" En el three-way diff:
" - Ventana izquierda: versión target (HEAD)
" - Ventana central: archivo de trabajo
" - Ventana derecha: versión merge
" Obtener cambios de una versión
:diffget //2 " Obtener de target (izquierda)
:diffget //3 " Obtener de merge (derecha)
" O usar atajos
do " diffget (obtener cambio)
dp " diffput (enviar cambio)
" Finalizar resolución
:Git add % " Stage archivo resuelto
:Git commit " Commit merge
Gestión de hunks (chunks de código)
" En modo diff o con gitgutter
]c " Siguiente hunk
[c " Hunk anterior
" Con vim-gitgutter (plugin adicional)
<Leader>hp " Preview hunk
<Leader>hs " Stage hunk
<Leader>hu " Undo hunk
Stash management
:Git stash " Crear stash
:Git stash pop " Aplicar último stash
:Git stash list " Listar stashes
:Git stash show " Mostrar último stash
:Git stash drop " Eliminar último stash
:Git stash apply stash@{0} " Aplicar stash específico
🔧 Plugins Complementarios
1. vim-gitgutter (Indicadores visuales)
Plug 'airblade/vim-gitgutter'
" Configuración
let g:gitgutter_enabled = 1
let g:gitgutter_map_keys = 0 " Deshabilitar mapeos por defecto
let g:gitgutter_highlight_lines = 0 " No resaltar líneas completas
let g:gitgutter_sign_added = '+'
let g:gitgutter_sign_modified = '~'
let g:gitgutter_sign_removed = '-'
" Mapeos personalizados
nnoremap <Leader>hp :GitGutterPreviewHunk<CR>
nnoremap <Leader>hs :GitGutterStageHunk<CR>
nnoremap <Leader>hu :GitGutterUndoHunk<CR>
nnoremap <Leader>hn :GitGutterNextHunk<CR>
nnoremap <Leader>hN :GitGutterPrevHunk<CR>
2. vim-git (Sintaxis mejorada)
Plug 'tpope/vim-git'
" Mejora sintaxis para archivos Git (commit messages, etc.)
3. gv.vim (Git log visual)
Plug 'junegunn/gv.vim'
" Comandos
:GV " Git log gráfico para todo el repo
:GV! " Git log solo para archivo actual
:GV? " Git log para buscar commits
" Navegación en GV
o " Abrir commit
O " Abrir commit en nueva tab
gb " Git blame
]] " Siguiente commit
[[ " Commit anterior
📝 Configuración Completa de Git
.vimrc optimizado para Git
" ============================================================================
" GIT CONFIGURATION
" ============================================================================
" Plugins
Plug 'tpope/vim-fugitive'
Plug 'airblade/vim-gitgutter'
Plug 'junegunn/gv.vim'
" Configuración básica
set diffopt+=vertical,filler,closeoff
autocmd BufReadPost fugitive://* set bufhidden=delete
" === MAPEOS FUGITIVE ===
nnoremap <Leader>g :Git<CR>
nnoremap <Leader>gs :Git status<CR>
nnoremap <Leader>gc :Git commit<CR>
nnoremap <Leader>gca :Git commit --amend<CR>
nnoremap <Leader>gp :Git push<CR>
nnoremap <Leader>gP :Git pull<CR>
nnoremap <Leader>gf :Git fetch<CR>
nnoremap <Leader>gl :Git log --oneline<CR>
nnoremap <Leader>gL :GV<CR>
nnoremap <Leader>gd :Gdiff<CR>
nnoremap <Leader>gb :Git blame<CR>
" Ramas
nnoremap <Leader>gco :Git checkout<Space>
nnoremap <Leader>gcb :Git checkout -b<Space>
nnoremap <Leader>gm :Git merge<Space>
" Stash
nnoremap <Leader>gst :Git stash<CR>
nnoremap <Leader>gsp :Git stash pop<CR>
nnoremap <Leader>gsl :Git stash list<CR>
" === MAPEOS GITGUTTER ===
let g:gitgutter_map_keys = 0
nnoremap <Leader>hp :GitGutterPreviewHunk<CR>
nnoremap <Leader>hs :GitGutterStageHunk<CR>
nnoremap <Leader>hu :GitGutterUndoHunk<CR>
nnoremap ]h :GitGutterNextHunk<CR>
nnoremap [h :GitGutterPrevHunk<CR>
" === CONFIGURACIÓN GITGUTTER ===
let g:gitgutter_enabled = 1
let g:gitgutter_highlight_lines = 0
let g:gitgutter_sign_added = '▎'
let g:gitgutter_sign_modified = '▎'
let g:gitgutter_sign_removed = '▎'
let g:gitgutter_sign_removed_first_line = '▎'
let g:gitgutter_sign_modified_removed = '▎'
" Actualización más rápida
set updatetime=250
" === AUTOCOMANDOS ===
augroup GitConfiguration
autocmd!
" Configuración para commit messages
autocmd FileType gitcommit setlocal spell spelllang=en,es
autocmd FileType gitcommit setlocal textwidth=72
autocmd FileType gitcommit startinsert
" Configuración para rebase interactivo
autocmd FileType gitrebase nnoremap <buffer> p :s/^pick/pick/<CR>
autocmd FileType gitrebase nnoremap <buffer> r :s/^pick/reword/<CR>
autocmd FileType gitrebase nnoremap <buffer> e :s/^pick/edit/<CR>
autocmd FileType gitrebase nnoremap <buffer> s :s/^pick/squash/<CR>
autocmd FileType gitrebase nnoremap <buffer> f :s/^pick/fixup/<CR>
autocmd FileType gitrebase nnoremap <buffer> d :s/^pick/drop/<CR>
augroup END
🔄 Workflows Específicos
Workflow 1: Feature Branch
" 1. Crear rama para feature
:Git checkout -b feature/nueva-funcionalidad
" 2. Hacer cambios y commits
:G " Ver status
" Stage archivos con 's' en la ventana status
cc " Commit (en ventana status)
" 3. Push de la rama
:Git push -u origin feature/nueva-funcionalidad
" 4. Crear Pull Request (desde GitHub/GitLab)
" 5. Merge y cleanup
:Git checkout main
:Git pull
:Git branch -d feature/nueva-funcionalidad
Workflow 2: Hotfix
" 1. Crear rama hotfix desde main
:Git checkout main
:Git pull
:Git checkout -b hotfix/bug-critico
" 2. Fix rápido
" ... hacer cambios ...
:G
cc " Commit rápido
" 3. Push y merge inmediato
:Git push -u origin hotfix/bug-critico
:Git checkout main
:Git merge hotfix/bug-critico
:Git push
:Git branch -d hotfix/bug-critico
Workflow 3: Code Review
" 1. Ver cambios de un commit
:Git show <commit-hash>
" 2. Ver diferencias entre ramas
:Git diff main..feature/rama
" 3. Blame para contexto
:Git blame
" 4. Log para historia
:GV " Visual git log
🧹 Comandos de Limpieza
Cleanup del repositorio
" Ver ramas
:Git branch -a
" Eliminar ramas locales mergeadas
:Git branch --merged | grep -v '\*\|main\|master' | xargs git branch -d
" Limpiar ramas remotas eliminadas
:Git remote prune origin
" Garbage collection
:Git gc
" Ver tamaño del repositorio
:Git count-objects -vH
Comandos de información
" Estado general
:Git status --porcelain
" Información del repositorio
:Git remote -v
:Git config --list
:Git log --stat
:Git shortlog -sn
" Buscar en la historia
:Git log -S "función_específica" " Buscar cuando se agregó/quitó
:Git log -G "patrón_regex" " Buscar cambios en patrón
:Git log --grep="mensaje" " Buscar en mensajes de commit
📝 Ejercicios Prácticos
Ejercicio 1: Setup y comandos básicos
- Instala vim-fugitive y vim-gitgutter
- Configura mapeos personalizados
- Practica workflow básico: status, stage, commit, push
- Explora la ventana de Git status
Ejercicio 2: Resolución de conflictos
- Crea dos ramas con cambios conflictivos
- Intenta merge para generar conflicto
- Usa :Gdiffsplit! para resolver
- Practica con diffget y diffput
Ejercicio 3: Git log y navegación
- Usa :GV para explorar historia
- Practica navegación entre commits
- Usa Git blame para entender cambios
- Busca commits específicos con diferentes criterios
Ejercicio 4: Workflow completo
- Simula un feature branch completo
- Haz múltiples commits organizados
- Usa stash durante el desarrollo
- Practica cleanup al final
🏆 Tips Pro
1. Aliases útiles de Git
# En ~/.gitconfig
[alias]
st = status
co = checkout
br = branch
ci = commit
ca = commit --amend
unstage = reset HEAD --
last = log -1 HEAD
visual = !gitk
tree = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
2. Configuración de merge tool
" En .vimrc para usar Vim como merge tool
if &diff
" Configuración específica para modo diff
set noro
map <Leader>1 :diffget LOCAL<CR>
map <Leader>2 :diffget BASE<CR>
map <Leader>3 :diffget REMOTE<CR>
endif
3. Funciones personalizadas
" Función para commit rápido
function! QuickCommit(message)
execute 'Git add .'
execute 'Git commit -m "' . a:message . '"'
endfunction
command! -nargs=1 Qcommit call QuickCommit(<q-args>)
" Función para branch rápido
function! QuickBranch(name)
execute 'Git checkout -b ' . a:name
endfunction
command! -nargs=1 Qbranch call QuickBranch(<q-args>)
4. Integración con status line
" Mostrar rama actual en statusline
function! GitBranch()
return system("git rev-parse --abbrev-ref HEAD 2>/dev/null | tr -d '\n'")
endfunction
set statusline+=%{GitBranch()}
🔗 Integración con Tmux
Workflow Git + Tmux
# Ventana dedicada a Git
tmux new-window -n 'git'
tmux send-keys 'vim' C-m
# En Vim, usar :G para management completo
# En panel adicional, comandos Git directos
tmux split-window -v
tmux send-keys 'git log --oneline' C-m
¡Con Fugitive y estas herramientas tendrás control total sobre Git sin salir de Vim!