diff --git a/README.md b/README.md
index f5dcd0637bf678bdec7666151a53bd84842f6d4a..f1a134c828fa7102b2bb4284434cc43d17a497a0 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,7 @@ This tool pull all public repo of some users FROM gitlab TO github.
 
 Gitlab is the actual dev repo, and github is a mirror. 
 
-Dependencies: fish, jq, git
+Dependencies: fish, json2table, git
+
+This doesn't recursively resolve gitlab sub-group. Please specify every sub-group as a new namespace. 
 
diff --git a/gitlab2github_sync.fish b/gitlab2github_sync.fish
index 455941056ffd19306ae8f4eb82b83b2f95f3dcb4..b463db49ea81b23c8b3309e77f78c07e1b48f591 100644
--- a/gitlab2github_sync.fish
+++ b/gitlab2github_sync.fish
@@ -1,5 +1,71 @@
 #!/usr/bin/fish
 
+set gitlab_host https://git.recolic.net
+# set gitlab_namespace_src users/root groups/recolic-hust
+set gitlab_namespace_src users/root
+set github_user_dst "rtestgithubapi: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"
+
+function echo2
+    echo $argv 1>&2
+end
+
+function sync_one_project
+    set project_name $argv[1]
+    set project_url $argv[2]
+    set github_project_desc "This is a read-only mirror for $project_url"
+    echo2 "Syncing $project_url to github:$github_user_dst..."
+
+    # Prepare github repository
+    set resp (curl -s -u $github_user_dst --data "{\"name\":\"$project_name\", \"description\":\"$github_project_desc\"}" https://api.github.com/user/repos)
+    if echo $resp | grep -F "name already exists on this account"
+        # Good. Update existing repo
+    else if echo $resp | grep -F $github_project_desc
+        echo2 "Creating new github repository success: $project_name"
+    else
+        echo2 "Failed to create or update github repo: $resp"
+        return 2
+    end
+    set github_username (echo $github_user_dst | sed 's/:.*$//g')
+    set github_project_url "https://$github_user_dst@github.com/$github_username/$project_name.git"
+
+    # Do the sync
+    test -d $project_name
+        or begin
+            git clone $project_url $project_name
+            and cd $project_name
+            and git remote add dst $github_project_url
+            and cd ..
+            or return 3
+        end
+
+    cd $project_name
+        # https://stackoverflow.com/questions/67054889/force-git-pull-to-resolve-divergent-by-discard-all-local-commits
+        and git fetch
+        and git reset --hard "@{upstream}"
+        and git push --tags --force dst (git branch --show-current)
+        and cd ..
+        or return 4
+end
+
+function do_namespace_copy
+    set ns_src $argv[1]
+    echo2 "Processing gitlab namespace $ns_src..."
+    set project_list (curl -s "$gitlab_host/api/v4/$ns_src/projects?per_page=9999" | json2table http_url_to_repo -p | grep VAL: | sed 's/^VAL: //g' | sed 's/|//g')
+    set workdir (pwd) # to avoid some failure in sync_one_project changes the workdir. 
+    for project_url in $project_list
+        set project_name (echo "$project_url" | sed 's/.git$//g' | sed 's/^.*\///g')
+        sync_one_project $project_name $project_url
+            or echo2 "sync_one_project fails for $project_name with status=$status"
+        sleep 10
+    end
+end
+
+for ns in $gitlab_namespace_src
+    do_namespace_copy $ns
+end
+
+
+
 
 
 
diff --git a/log b/log
deleted file mode 100644
index fdc62ea0fa1c0695841fc8db7b90ed9caf184178..0000000000000000000000000000000000000000
--- a/log
+++ /dev/null
@@ -1,8 +0,0 @@
-curl https://git.recolic.net/api/v4/users/root/projects
-
-
-curl -u "rtestgithubapi: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" --data '{"name":"NEW_REPO_NAME"}' https://api.github.com/user/repos
-curl -u "rtestgithubapi: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" --request PATCH --data '{"name":"NEW_REPO_NAME", "description":"a new description"}' https://api.github.com/repos/rtestgithubapi/NEW_REPO_NAME
-
-
-