---
title: Git Symbolic Links Setup for Blog Content 
pubDate: 2023-11-01
description: A comprehensive guide to setting up Git with symbolic links for efficient content management between Obsidian and your blog codebase
author: LaForce IT
heroImage: /images/git-symlinks-hero.jpg
category: Development
tags:
  - git
  - obsidian
  - workflow
  - automation
---

# Git Symbolic Links Setup for Blog Content

## Overview

This document explains the setup that allows the blog content to be managed in Obsidian while being properly versioned in Git. The setup uses Git hooks to automatically handle symbolic links, ensuring that actual content is committed while maintaining symbolic links for local development.

## Architecture

```mermaid
graph TD
    A[Obsidian Vault] -->|Symbolic Links| B[Blog Repository]
    B -->|Pre-commit Hook| C[Convert to Content]
    C -->|Commit| D[Git Repository]
    D -->|Post-commit Hook| E[Restore Symlinks]
    E -->|Local Development| B
```

## Directory Structure

### Obsidian Content Location
```
/mnt/synology/obsidian/Public/Blog/
├── posts/
├── projects/
├── configurations/
├── external-posts/
├── configs/
├── images/
├── infrastructure/
└── content/
```

### Blog Repository Structure
```
laforceit-blog/
├── src/content/
│   ├── posts -> /mnt/synology/obsidian/Public/Blog/posts
│   ├── projects -> /mnt/synology/obsidian/Public/Blog/projects
│   ├── configurations -> /mnt/synology/obsidian/Public/Blog/configurations
│   └── external-posts -> /mnt/synology/obsidian/Public/Blog/external-posts
└── public/blog/
    ├── configs -> /mnt/synology/obsidian/Public/Blog/configs
    ├── images -> /mnt/synology/obsidian/Public/Blog/images
    ├── infrastructure -> /mnt/synology/obsidian/Public/Blog/infrastructure
    └── posts -> /mnt/synology/obsidian/Public/Blog/posts
```

## Setup Instructions

1. Clone the Blog Repository
```bash
git clone https://git.argobox.com/KeyArgo/laforceit-blog.git
cd laforceit-blog
```

2. Create the Scripts Directory
```bash
mkdir -p scripts
```

3. Create the Content Processing Script
Create `scripts/process-content-links.sh`:
```bash
#!/bin/bash

# Script to handle symbolic links before commit
echo "Processing symbolic links for content..."

# Array of content directories to process
declare -A CONTENT_PATHS
# src/content directories
CONTENT_PATHS["posts"]="src/content/posts"
CONTENT_PATHS["projects"]="src/content/projects"
CONTENT_PATHS["configurations"]="src/content/configurations"
CONTENT_PATHS["external-posts"]="src/content/external-posts"
# public/blog directories
CONTENT_PATHS["configs"]="public/blog/configs"
CONTENT_PATHS["images"]="public/blog/images"
CONTENT_PATHS["infrastructure"]="public/blog/infrastructure"
CONTENT_PATHS["blog-posts"]="public/blog/posts"

for dir_name in "${!CONTENT_PATHS[@]}"; do
    dir_path="${CONTENT_PATHS[$dir_name]}"
    if [ -L "$dir_path" ]; then
        echo "Processing $dir_path..."
        target=$(readlink "$dir_path")
        rm "$dir_path"
        mkdir -p "$(dirname "$dir_path")"
        cp -r "$target" "$dir_path"
        git add "$dir_path"
        echo "Processed $dir_path -> $target"
    else
        echo "Skipping $dir_path (not a symbolic link)"
    fi
done

echo "Content processing complete!"
```

4. Create Git Hooks

### Pre-commit Hook
Create `.git/hooks/pre-commit`:
```bash
#!/bin/bash
# Pre-commit hook to process symbolic links

echo "Running pre-commit hook for blog content..."

# Get the absolute path to the script
SCRIPT_PATH="$(git rev-parse --show-toplevel)/scripts/process-content-links.sh"

# Check if the script exists and is executable
if [ -x "$SCRIPT_PATH" ]; then
    bash "$SCRIPT_PATH"
    # Add any new or changed files resulting from the script
    git add -A
else
    echo "Error: Content processing script not found or not executable at $SCRIPT_PATH"
    echo "Please ensure the script exists and has execute permissions"
    exit 1
fi
```

### Post-commit Hook
Create `.git/hooks/post-commit`:
```bash
#!/bin/bash
# Post-commit hook to restore symbolic links

echo "Running post-commit hook to restore symbolic links..."

# Array of content directories and their targets
declare -A SYMLINK_TARGETS=(
    ["src/content/posts"]="/mnt/synology/obsidian/Public/Blog/posts"
    ["src/content/projects"]="/mnt/synology/obsidian/Public/Blog/projects"
    ["src/content/configurations"]="/mnt/synology/obsidian/Public/Blog/configurations"
    ["src/content/external-posts"]="/mnt/synology/obsidian/Public/Blog/external-posts"
    ["public/blog/configs"]="/mnt/synology/obsidian/Public/Blog/configs"
    ["public/blog/images"]="/mnt/synology/obsidian/Public/Blog/images"
    ["public/blog/infrastructure"]="/mnt/synology/obsidian/Public/Blog/infrastructure"
    ["public/blog/posts"]="/mnt/synology/obsidian/Public/Blog/posts"
)

for dir_path in "${!SYMLINK_TARGETS[@]}"; do
    target="${SYMLINK_TARGETS[$dir_path]}"
    if [ -d "$target" ]; then
        echo "Restoring symlink for $dir_path -> $target"
        rm -rf "$dir_path"
        mkdir -p "$(dirname "$dir_path")"
        ln -s "$target" "$dir_path"
    else
        echo "Warning: Target directory $target does not exist"
    fi
done

echo "Symbolic links restored!"
```

5. Set Proper Permissions
```bash
chmod +x scripts/process-content-links.sh
chmod +x .git/hooks/pre-commit
chmod +x .git/hooks/post-commit
```

6. Create Symbolic Links
```bash
# Create necessary directories
mkdir -p src/content public/blog

# Create symbolic links for src/content
ln -s /mnt/synology/obsidian/Public/Blog/posts src/content/posts
ln -s /mnt/synology/obsidian/Public/Blog/projects src/content/projects
ln -s /mnt/synology/obsidian/Public/Blog/configurations src/content/configurations
ln -s /mnt/synology/obsidian/Public/Blog/external-posts src/content/external-posts

# Create symbolic links for public/blog
ln -s /mnt/synology/obsidian/Public/Blog/configs public/blog/configs
ln -s /mnt/synology/obsidian/Public/Blog/images public/blog/images
ln -s /mnt/synology/obsidian/Public/Blog/infrastructure public/blog/infrastructure
ln -s /mnt/synology/obsidian/Public/Blog/posts public/blog/posts
```

## Git Configuration

1. Configure Git to Handle Symbolic Links
```bash
git config core.symlinks true
```

2. Create `.gitattributes`
```
# Handle symbolic links as real content
public/blog/* !symlink
src/content/* !symlink

# Treat these directories as regular directories even if they're symlinks
public/blog/configs/ -symlink
public/blog/images/ -symlink
public/blog/infrastructure/ -symlink
public/blog/posts/ -symlink
src/content/posts/ -symlink
src/content/projects/ -symlink
src/content/configurations/ -symlink
src/content/external-posts/ -symlink

# Set text files to automatically normalize line endings
* text=auto
```

## How It Works

1. **Normal Development**
   - Content is edited in Obsidian
   - Blog repository uses symbolic links to this content
   - Local development works seamlessly

2. **During Commits**
   - Pre-commit hook activates
   - Symbolic links are converted to actual content
   - Content is committed to the repository

3. **After Commits**
   - Post-commit hook activates
   - Symbolic links are restored
   - Local development continues normally

## Viewing in Gitea

Yes, you can view this setup in Gitea:
1. The actual content will be visible in the repository
2. The `.git/hooks` directory and scripts will be visible
3. The symbolic links will appear as regular directories in Gitea

## Troubleshooting

1. **Symbolic Links Not Working**
   - Check file permissions
   - Verify Obsidian vault location
   - Ensure Git symlinks are enabled

2. **Hooks Not Executing**
   - Check execute permissions on scripts
   - Verify hook files are in `.git/hooks`
   - Check script paths are correct

3. **Content Not Committing**
   - Check Git configuration
   - Verify pre-commit hook execution
   - Check file permissions

## Maintenance

1. **Adding New Content Directories**
   - Add to `CONTENT_PATHS` in process-content-links.sh
   - Add to `SYMLINK_TARGETS` in post-commit hook
   - Create corresponding symbolic links

2. **Changing Obsidian Location**
   - Update paths in post-commit hook
   - Update existing symbolic links

3. **Backup Considerations**
   - Both Obsidian content and blog repository should be backed up
   - Keep hooks and scripts in version control

## Security Notes

1. Keep sensitive content outside of public blog directories
2. Review content before commits
3. Use `.gitignore` for private files
4. Consider access permissions on Obsidian vault
