Location>code7788 >text

Multi-end synchronization of notes with Joplin + Git + Gitee

Popularity:260 ℃/2025-04-27 19:44:20

1-Remote warehouse environment preparation

1.1-Register Gitee Account

Since Git is used as a version control tool, it is OK as long as it is a hosting platform supported by Git. For example, Github and Gitlab. The use of Gitee here is mainly because it is easier to access Gitee on Android.

1.2-Create a remote repository

Create aRemote warehouse, used to store notes and files.

2-Local warehouse environment preparation

The core tool for multi-terminal synchronization isGit, so first of all,EachConfigure on the platform that needs to be synchronizedGitenvironment.

2.1-Installation and configuration Git

It is very easy to install and configure Git on the PC side, so I won’t go into details. I will mainly talk about the Android side here.

GitThere is no Android version directly provided, so you need helpTermuxOn this Android platformTerminal emulatorto install and run.

useTermuxAnother feature is that many operations are consistent with Linux platforms, such as later usebashThe scripts perform synchronization operations between local and remote repositories. Linux and Android can use exactly the same scripts except for different path information.

Therefore, first installTermux

2.1.1-InstallationTermux

TermuxCan be passedF-DroidOr fromGithubDownload the installation package to install.

2.1.2-forTermuxObtain device storage access permissions

Due to the particularity of the Android environment,TermuxThere is no access permission for Android device storage, because a series of operations will be performed on the local repository folder in the future, so this one is verynecessaryandimportantof.

  1. existTermuxExecute the following command:
    termux-setup-storage
  2. After that, the phone will prompt for authorization.agreeJust do it.

after,TermuxWill be hereTable of contents(~yesTermuxDefault user'sHomeDirectory, corresponding to the actual storage of the mobile phone/data/data//files/homeCreate several directories under the directory)MappingThe corresponding directories of the mobile phone are of course in/storage/emulated/0Directory below. The specific mapping situation is as follows:

TermuxPath in Actual paths in mobile phone storage illustrate
~/storage/shared /storage/emulated/0 Equivalent to the default user of the phoneHomeTable of contents.
~/storage/downloads /storage/emulated/0/Download Files downloaded from system browsers and other applications are saved by default.
~/storage/dcim /storage/emulated/0/DCIM A regular storage directory for pictures and videos captured by the camera.
~/storage/pictures /storage/emulated/0/Pictures A user-accessible image storage directory.
~/storage/music /storage/emulated/0/Music Audio file storage directory in user music list.
~/storage/movies /storage/emulated/0/Movies A directory of movie storage that users can access.
~/storage/external-1 External memory card path (if present) If the device has an external memory card, this directory is mapped to the Termux private folder of the external memory card.

The key point here is~/storage/shared -> /storage/emulated/0

Anyway, you canTermuxUse mapped paths to access the mobile phone directory, including subsequentTermuxAccess, git operations, and bash scripts are all used to access them using mapped paths.

2.1.3-InTermuxInstalled in the middleGit

Termux's default package manager ispkg. Customary, before installing a specific package using the package manager, you should firstUpdate package index

  1. renewpkgPackage index.
    existTermuxEnter the following command:
    pkg update
  2. InstallGit
    existTermuxEnter the following command:
    pkg install git

At this point, the installation of Git for Android platform is completed.

2.1.4-Configure Git User Information

Configure local GitandInformation, this is essential for Git push operations.

existTermuxEnter the following two commands:

  1. git config --global "your name"
  2. git config --global "your@"

in,

  • configIndicates that this command is used to configure something;
  • --globalIt means configuration global information, that is, the configured content takes effect on all local Git repositories under the current user. This is not necessary, but it is recommended to do so if there are no special needs;
  • andIt is the object to be configured, and these two information are essential for push operations;
  • The last string is the configuration content, which is generally consistent with the information on the code hosting platform.

2.2-Configure SSH Key

createSSH keyIt's for useSSH protocolMore convenient and fastRemote warehouseconductPullandPush

SSHA key is an encryption technology, an SSH key contains aPublic KeyAnd onePrivate key, The public key is used to publicize it to others. Only the corresponding private key can be decrypted after the data is encrypted by others using this public key. Therefore, SSH encryption technology is often used for one-way communication.

A pair of SSH keys are required to be generated on each platform.

  1. Generate an SSH key
    The commands for generating SSH keys for each platform are basically the same:
    ssh-keygen -t rsa -C "Comment Information"
    in,
    • ssh-keygenyesOpenSSHA tool provided for generating SSH key pairs;
    • -t rsaSpecifies the type of key or the encryption algorithm used;
    • -C "Comment Information"The comment information for the key is specified, which is not necessary, but it is usually done to use your email address as the comment information.

Enter the command and press Enter all the way.

  1. Put each platform'sPublic KeyAdd to hosting platform

After the previous step is generated~/.sshThere will be a directoryid_rsaandid_rsa.pubTwo text files, whereid_rsaThe private key is stored.id_rsa.pubWhat is stored is the public key, which will be placed on each platformid_rsa.pubThe contents in the file are copied separately and added to the SSH public key list of the hosting platform.

2.3-Create and configure local repository

2.3.1-Create a local repository

  1. First, create a folder for storing notes on each platform. It is recommended to use a unified name, such asJoplin

Android, for the Joplin software andYou yourselfIt is easy to access, it is recommended to create the directory in/storage/emulated/0Below, for example/storage/emulated/0/Joplin

  1. Initialize the Git repository, enter the repository directory, and enter the following command:
    git init .

  2. Configure the link to the remote repository

First, you should obtain the remote repositorySSH link, it is recommended to copy and paste to avoid errors. You can find it in the page of the remote repository. Note that the SSH link is looking for, which should look like the following:

git@:mtueih/

In the repository directory, enter the following command:

git remote add origin "git@:mtueih/"

Note that the following link is replaced with the SSH link of your repository.

★【For Android】Add the repository directory to the list of Git's secure directory

In security considerations, when performing a Git operation, if the ownership of the target repository of the operation does not belong to the user performing the operation, the operation will not be executed, and Git will give an error message. In short, Git only allowsyouRightyouThe warehouse performs operations.

existTermuxIn an environment, it is usually executed as its default user.Gitoperation, and created in/storage/emulated/0The ownership of the Git repository below is notTermuxofDefault userIt's the mobile phoneDefault user, or because the path to this repository is outside the Home directory of Termux's default user, this will lead to the aforementioned problem.

As mentioned earlier, create the repository directory in/storage/emulated/0/JoplinIt is a last resort, so there are two solutions: one is to modify the ownership of the repository, and the other is to add the repository directory to the secure directory list of the global Git configuration of the default user of Termux. The second method is used here.

Execute the following command in Termux:

git config --global --add /storage/emulated/0/joplin

Here you need to modify the subsequent repository path to the actual path of your repository. After experimenting, use the absolute/relative path mapped by Termux here (/data/data//files/home/storage/shared/joplinor~/storage/shared/joplin), and the actual path to the mobile phone storage (/storage/emulated/0/joplin), all three are OK, but before the Git command is solved, the error message given by Git is used/storage/emulated/0/joplin, as for why, we don’t know.


At this point, the remote and local warehouse environment is ready. Next, you need to set it upJoplinto allow it to output synchronous content to the local repository folder.

3-Set the synchronization path of Joplin

The steps of this step on each platform are similar. Go to Joplin's settings for synchronization, change the synchronization target to the file system, and then enter/select the repository path you created before.

To encrypt, you need to set the same master password on each platform.

4-Simplify synchronization process through scripts

At this point, the synchronization of the three ends has been actually built, but it is really true that you have to type a lot of commands to synchronize every time, especially on the Android side. In addition, we may need to trigger synchronization operations automatically and regularly, so we have to rely on scripts.

Due to the parent-child relationship between operating systems, it is actually only necessary to write two scripts for different platforms (of course, each platform may have slight differences) just fine: Powershell scripts (what? 😅No one will install Powershell with Windows, right? That bat script is OK too) and Bash scripts.

4.1-Bash script

Since Bash is almost all Unix-class environments (includingTermux) default shell tool, so write Bash scripts here.

Here we take the Android side as an example.

★After actual testing, it can only be used on Android/storage/emulated/0/joplinor/data/data//files/home/storage/shared/joplinThese two absolute paths,~/storage/shared/joplinThat's not possible, Git will not find this path.

#!/bin/bash

 # Set the local warehouse path (modify according to actual situation)
 repo_path="/storage/emulated/0/joplin"

 # Switch to the local repository directory
 cd $repo_path

 # Check for any uncommitted changes
 if git status --porcelain | grep -q .; then
     echo "Local changes were detected, ready to submit..."
     # Add all changes to the temporary storage area
     git add .
     # Submit changes, using the current time as submission information
     commit_message="Automatically submitted in $(date +%Y-%m-%d\ %H:%M:%S)"
     git commit -m "$commit_message"
     echo "Local changes have been submitted."
 else
     echo "There are no uncommitted changes locally."
 fi

 # Get the latest commit hash value for remote and local repositories
 local_hash=$(git rev-parse HEAD)
 git fetch origin main
 remote_hash=$(git rev-parse origin/main)

 # Comparison of hash values ​​for local and remote repositories
 if [ "$local_hash" != "$remote_hash" ]; then
     # Check whether the local hash value is included in the remote branch
     if git merge-base --is-ancestor $remote_hash $local_hash; then
         echo "Local repository is newer than remote repository, ready to push changes..."
         git push origin main
         echo "Push completed."
     elif git merge-base --is-ancestor $local_hash $remote_hash; then
         echo "Remote repository is newer than local repository, ready to pull changes..."
         git pull origin main
         echo "Pull done."
     else
         # There is a disagreement between local and remote repositories, and ask the user which version to retain
         echo "There are differences between local and remote repositories. Please choose which version to keep:"
         echo "1) Keep the remote version (pull --rebase)"
         echo "2) Keep the local version (push --force)"
         echo "3) Manual conflict resolution"
         read -p "Please select an option (1/2/3): " user_choice

         if [ "$user_choice" == "1" ]; then
             echo "Prepare to pull remote changes and rebase..."
             git pull --rebase origin main
             echo "Pull and change the base to complete."
         elif [ "$user_choice" == "2" ]; then
             echo "Prepare to force push local changes..."
             git push --force origin main
             echo "Forced push is completed."
         elif [ "$user_choice" == "3" ]; then
             echo "Please resolve the conflict manually."
             # Here you can add steps to resolve conflicts manually, such as using git mergetool
         else
             echo "Invalid selection, script terminates."
         fi
     fi
 else
     echo "Remote repository and local repository are synchronized without operation."
 fi

Other platforms (except Windows) only have different repository paths, and the rest are the same.

4.2-Powershell scripts

# Set the local warehouse path (modify according to actual situation)
 $repo_path = "E:\Joplin"

 # Switch to the local repository directory
 Set-Location -Path $repo_path

 # Check for any uncommitted changes
 $git_status = git status --porcelain
 if ($git_status) {
     Write-Host "Local changes were detected, ready to submit..."
     # Add all changes to the temporary storage area
     git add .
     # Submit changes, using the current time as submission information
     $commit_message = "Automatically submitted in $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
     git commit -m $commit_message
     Write-Host "Local changes have been submitted."
 } else {
     Write-Host "There are no uncommitted changes locally."
 }

 # Get the latest commit hash value for remote and local repositories
 $local_hash = git rev-parse HEAD
 git fetch origin main
 $remote_hash = git rev-parse origin/main

 # Comparison of hash values ​​for local and remote repositories
 if ($local_hash -ne $remote_hash) {
     # Check whether the local hash value is included in the remote branch
     if (git merge-base --is-ancestor $remote_hash $local_hash) {
         Write-Host "Local repository is newer than remote repository, ready to push changes..."
         git push origin main
         Write-Host "Push completed."
     } elseif (git merge-base --is-ancestor $local_hash $remote_hash) {
         Write-Host "Remote repository is newer than local repository, ready to pull changes..."
         git pull origin main
         Write-Host "Pull done."
     } else {
         # There is a disagreement between local and remote repositories, and ask the user which version to retain
         Write-Host "There are differences between local and remote repositories. Please choose which version to keep:"
         Write-Host "1) Remote version (pull --rebase)"
         Write-Host "2) Keep the local version (push --force)"
         Write-Host "3) Manual conflict resolution"
         $user_choice = Read-Host "Please select an option (1/2/3)"

         if ($user_choice -eq "1") {
             Write-Host "Prepare to pull remote changes and rebase..."
             git pull --rebase origin main
             Write-Host "Pull and change the base to complete."
         } elseif ($user_choice -eq "2") {
             Write-Host "Prepare to force push local changes..."
             git push --force origin main
             Write-Host "Forced push is completed."
         } elseif ($user_choice -eq "3") {
             Write-Host "Please resolve the conflict manually."
             # Here you can add steps to resolve conflicts manually, such as using git mergetool
         } else {
             Write-Host "Invalid selection, script terminates."
         }
     }
 } else {
     Write-Host "Remote repository and local repository are synchronized without operation."
 }