#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, maxm = 2e5 + 5, maxq = 2e5 + 5;
struct edge {
  int x, y, d;
} e[maxm + maxq];
int len = 0;
int s[maxn + maxq], t[maxn + maxq];
int q[maxq][3];
int f[maxn], rk[maxn], dis[maxn];
int ans[maxq];
map<long long, int> mp;
vector<int> upd[maxq << 2];
vector<int> que[maxq << 2];
int read() {
  int x = 0, y = 1;
  char ch = getchar();
  while (ch < 48 || ch > 57) {
    if (ch == 45) y = -1;
    ch = getchar();
  }
  while (ch >= 48 && ch <= 57)
    x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
  return x * y;
}
void modify1(int k, int l, int r, int x, int y, int id) {
  if (l > y || r < x) return;
  if (l >= x && r <= y) {
    upd[k].push_back(id);
    return;
  }
  int mid = l + ((r - l) >> 1);
  modify1(k << 1, l, mid, x, y, id);
  modify1(k << 1 | 1, mid + 1, r, x, y, id);
  return;
}
void modify2(int k, int l, int r, int x, int id) {
  if (l > x || r < x) return;
  if (l == r) {
    que[k].push_back(id);
    return;
  }
  int mid = l + ((r - l) >> 1);
  modify2(k << 1, l, mid, x, id);
  modify2(k << 1 | 1, mid + 1, r, x, id);
  return;
}
void ins(int x, int *p) {
  for (int i = 29; i >= 0; i--) {
    if (!x) return;
    if (!(x & (1 << i))) continue;
    if (!p[i]) {
      p[i] = x;
      return;
    }
    x ^= p[i];
  }
  return;
}
int query(int val, int *p) {
  int ans = val;
  for (int i = 29; i >= 0; i--)
    if ((ans ^ p[i]) < ans) ans ^= p[i];
  return ans;
}
int find(int x) {
  if (f[x] == x) return x;
  return find(f[x]);
}
int getd(int x) {
  if (f[x] == x) return 0;
  return dis[x] ^ getd(f[x]);
}
int tp = 0;
int px[maxn], pd[maxn], pr[maxn];
int update(int k, int *p) {
  int siz = 0;
  for (int i = 0; i < upd[k].size(); i++) {
    int id = upd[k][i];
    int u = e[id].x, v = e[id].y;
    int x = find(u), y = find(v), d = e[id].d;
    d ^= (getd(u) ^ getd(v));
    if (rk[x] > rk[y]) swap(x, y);
    if (x != y) {
      tp++;
      px[tp] = x;
      pd[tp] = dis[x];
      dis[x] = d;
      f[x] = y;
      pr[tp] = rk[y];
      if (rk[x] == rk[y]) rk[y]++;
      siz++;
    } else
      ins(d, p);
  }
  return siz;
}
void clear(int k, int siz) {
  while (siz--) {
    int x = px[tp], y = f[x];
    f[x] = x;
    dis[x] = pd[tp];
    rk[y] = pr[tp];
    tp--;
  }
  return;
}
void solve(int k, int l, int r, int *p) {
  int siz = update(k, p);
  if (l == r) {
    for (int i = 0; i < que[k].size(); i++) {
      int id = que[k][i];
      ans[id] = query(getd(q[id][1]) ^ getd(q[id][2]), p);
    }
    clear(k, siz);
    return;
  }
  int mid = l + ((r - l) >> 1);
  int h[30];
  for (int i = 0; i <= 29; i++) h[i] = p[i];
  solve(k << 1, l, mid, h);
  for (int i = 0; i <= 29; i++) h[i] = p[i];
  solve(k << 1 | 1, mid + 1, r, h);
  clear(k, siz);
  return;
}
int main() {
  long long n, m, qq;
  n = read();
  m = read();
  for (int i = 1; i <= m; i++) {
    long long x, y, d;
    x = read();
    y = read();
    d = read();
    if (x > y) swap(x, y);
    mp[x * n + y] = i;
    e[i].x = x;
    e[i].y = y;
    e[i].d = d;
    s[i] = 1;
  }
  len = m;
  qq = read();
  int tim = 1, Q = 0;
  for (int i = 1; i <= qq; i++) {
    long long opt, x, y, d;
    opt = read();
    x = read();
    y = read();
    if (x > y) swap(x, y);
    if (opt == 1) {
      d = read();
      mp[x * n + y] = ++len;
      e[len].x = x;
      e[len].y = y;
      e[len].d = d;
      s[len] = ++tim;
    } else if (opt == 2) {
      int id = mp[x * n + y];
      t[id] = tim++;
    } else {
      Q++;
      q[Q][0] = tim;
      q[Q][1] = x;
      q[Q][2] = y;
    }
  }
  for (int i = 1; i <= len; i++) {
    if (!t[i]) t[i] = tim;
    modify1(1, 1, tim, s[i], t[i], i);
  }
  for (int i = 1; i <= Q; i++) modify2(1, 1, tim, q[i][0], i);
  for (int i = 1; i <= n; i++) f[i] = i, dis[i] = 0, rk[i] = 1;
  int p[30];
  for (int i = 0; i <= 29; i++) p[i] = 0;
  for (int i = 1; i <= Q; i++) ans[i] = 1 << 30;
  solve(1, 1, tim, p);
  for (int i = 1; i <= Q; i++) printf("%d\n", ans[i]);
  return 0;
}
